Changeset 91021 in webkit
- Timestamp:
- Jul 14, 2011 12:24:24 PM (13 years ago)
- Location:
- trunk/Tools
- Files:
-
- 8 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Tools/ChangeLog
r91011 r91021 1 2011-07-14 Ojan Vafai <ojan@chromium.org> 2 3 fix coding style of dashboard_base.js 4 https://bugs.webkit.org/show_bug.cgi?id=64545 5 6 Reviewed by Adam Roben. 7 8 The code changes to the files other than dashboard_base.js 9 are just fallout from renaming globals in dashboard_base.js. 10 11 * TestResultServer/static-dashboards/aggregate_results.html: 12 * TestResultServer/static-dashboards/builders.js: 13 * TestResultServer/static-dashboards/dashboard_base.js: 14 * TestResultServer/static-dashboards/flakiness_dashboard.html: 15 * TestResultServer/static-dashboards/flakiness_dashboard_tests.js: 16 * TestResultServer/static-dashboards/timeline_explorer.html: 17 * TestResultServer/static-dashboards/treemap.html: 18 1 19 2011-07-14 Carlos Garcia Campos <cgarcia@igalia.com> 2 20 -
trunk/Tools/TestResultServer/static-dashboards/aggregate_results.html
r90674 r91021 70 70 function generatePage() { 71 71 var html = getHTMLForTestTypeSwitcher(true) + '<br>'; 72 for (var builder in builders) {72 for (var builder in g_builders) { 73 73 html += getHTMLForBuilder(builder); 74 74 } … … 79 79 switch(key) { 80 80 case 'rawValues': 81 currentState[key] = value == 'true';81 g_currentState[key] = value == 'true'; 82 82 83 83 return true; … … 88 88 } 89 89 90 defaultStateValues = {90 g_defaultStateValues = { 91 91 rawValues: false 92 92 }; 93 93 94 94 function getHTMLForBuilder(builder) { 95 var results = resultsByBuilder[builder];95 var results = g_resultsByBuilder[builder]; 96 96 // Some keys were added later than others, so they don't have as many 97 97 // builds. Use the shortest. … … 102 102 var html = '<div class=container><h2>' + builder + '</h2>'; 103 103 104 if ( currentState.rawValues) {104 if (g_currentState.rawValues) { 105 105 html += getRawValuesHTML(results, numColumns); 106 106 } else { -
trunk/Tools/TestResultServer/static-dashboards/builders.js
r90674 r91021 74 74 // TODO(mihaip): instead of copying these to globals, it would be better if 75 75 // the rest of the code read things from the BuilderGroup instance directly 76 defaultBuilderName = this.defaultBuilder;77 expectationsBuilder = this.expectationsBuilder;78 builders = this.builders;76 g_defaultBuilderName = this.defaultBuilder; 77 g_expectationsBuilder = this.expectationsBuilder; 78 g_builders = this.builders; 79 79 }; 80 80 -
trunk/Tools/TestResultServer/static-dashboards/dashboard_base.js
r90964 r91021 1 /* 2 * Copyright (C) 2011 Google Inc. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions are 6 * met: 7 * 8 * * Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * * Redistributions in binary form must reproduce the above 11 * copyright notice, this list of conditions and the following disclaimer 12 * in the documentation and/or other materials provided with the 13 * distribution. 14 * * Neither the name of Google Inc. nor the names of its 15 * contributors may be used to endorse or promote products derived from 16 * this software without specific prior written permission. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 */ 30 31 /** 32 * @fileoverview Base JS file for pages that want to parse the results JSON 33 * from the testing bots. This deals with generic utility functions, visible 34 * history, popups and appending the script elements for the JSON files. 35 * 36 * The calling page is expected to implement the following "abstract" 37 * functions/objects: 38 */ 39 var pageLoadStartTime = Date.now(); 40 41 /** 42 * Generates the contents of the dashboard. The page should override this with 43 * a function that generates the page assuming all resources have loaded. 44 */ 45 function generatePage() { 46 } 47 48 /** 49 * Takes a key and a value and sets the currentState[key] = value iff key is 50 * a valid hash parameter and the value is a valid value for that key. 51 * 52 * @return {boolean} Whether the key what inserted into the currentState. 53 */ 54 function handleValidHashParameter(key, value) { 55 return false; 56 } 57 58 /** 59 * Default hash parameters for the page. The page should override this to create 60 * default states. 61 */ 62 var defaultStateValues = {}; 63 64 65 /** 66 * The page should override this to modify page state due to 67 * changing query parameters. 68 * @param {Object} params New or modified query params as key: value. 69 * @return {boolean} Whether changing this parameter should cause generatePage to be called. 70 */ 71 function handleQueryParameterChange(params) { 72 return true; 1 // Copyright (C) 2011 Google Inc. All rights reserved. 2 // 3 // Redistribution and use in source and binary forms, with or without 4 // modification, are permitted provided that the following conditions are 5 // met: 6 // 7 // * Redistributions of source code must retain the above copyright 8 // notice, this list of conditions and the following disclaimer. 9 // * Redistributions in binary form must reproduce the above 10 // copyright notice, this list of conditions and the following disclaimer 11 // in the documentation and/or other materials provided with the 12 // distribution. 13 // * Neither the name of Google Inc. nor the names of its 14 // contributors may be used to endorse or promote products derived from 15 // this software without specific prior written permission. 16 // 17 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 21 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 23 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 29 // @fileoverview Base JS file for pages that want to parse the results JSON 30 // from the testing bots. This deals with generic utility functions, visible 31 // history, popups and appending the script elements for the JSON files. 32 // 33 // The calling page is expected to implement the following "abstract" 34 // functions/objects: 35 var g_pageLoadStartTime = Date.now(); 36 37 // Generates the contents of the dashboard. The page should override this with 38 // a function that generates the page assuming all resources have loaded. 39 function generatePage() {} 40 41 // Takes a key and a value and sets the g_currentState[key] = value iff key is 42 // a valid hash parameter and the value is a valid value for that key. 43 // 44 // @return {boolean} Whether the key what inserted into the g_currentState. 45 function handleValidHashParameter(key, value) 46 { 47 return false; 48 } 49 50 // Default hash parameters for the page. The page should override this to create 51 // default states. 52 var g_defaultStateValues = {}; 53 54 55 // The page should override this to modify page state due to 56 // changing query parameters. 57 // @param {Object} params New or modified query params as key: value. 58 // @return {boolean} Whether changing this parameter should cause generatePage to be called. 59 function handleQueryParameterChange(params) 60 { 61 return true; 73 62 } 74 63 … … 77 66 ////////////////////////////////////////////////////////////////////////////// 78 67 var GTEST_EXPECTATIONS_MAP_ = { 79 'P': 'PASS',80 'F': 'FAIL',81 'L': 'FLAKY',82 'N': 'NO DATA',83 'X': 'DISABLED'68 'P': 'PASS', 69 'F': 'FAIL', 70 'L': 'FLAKY', 71 'N': 'NO DATA', 72 'X': 'DISABLED' 84 73 }; 85 74 86 75 var LAYOUT_TEST_EXPECTATIONS_MAP_ = { 87 'P': 'PASS',88 'N': 'NO DATA',89 'X': 'SKIP',90 'T': 'TIMEOUT',91 'F': 'TEXT',92 'C': 'CRASH',93 'I': 'IMAGE',94 'Z': 'IMAGE+TEXT',95 // We used to glob a bunch of expectations into "O" as OTHER. Expectations96 // are more precise now though and it just means MISSING.97 'O': 'MISSING'76 'P': 'PASS', 77 'N': 'NO DATA', 78 'X': 'SKIP', 79 'T': 'TIMEOUT', 80 'F': 'TEXT', 81 'C': 'CRASH', 82 'I': 'IMAGE', 83 'Z': 'IMAGE+TEXT', 84 // We used to glob a bunch of expectations into "O" as OTHER. Expectations 85 // are more precise now though and it just means MISSING. 86 'O': 'MISSING' 98 87 }; 99 88 100 89 var FAILURE_EXPECTATIONS_ = { 101 'T': 1,102 'F': 1,103 'C': 1,104 'I': 1,105 'Z': 190 'T': 1, 91 'F': 1, 92 'C': 1, 93 'I': 1, 94 'Z': 1 106 95 }; 107 96 … … 124 113 // See http://test-results.appspot.com/testfile. 125 114 var TEST_TYPES = ['app_unittests', 'base_unittests', 'browser_tests', 126 'cache_invalidation_unittests', 'courgette_unittests',127 'crypto_unittests', 'googleurl_unittests', 'gpu_unittests',128 'installer_util_unittests', 'interactive_ui_tests', 'ipc_tests',129 'jingle_unittests', 'layout-tests', 'media_unittests',130 'mini_installer_test', 'nacl_ui_tests', 'net_unittests',131 'printing_unittests', 'remoting_unittests', 'safe_browsing_tests',132 'sync_unit_tests', 'sync_integration_tests',133 'test_shell_tests', 'ui_tests', 'unit_tests'];115 'cache_invalidation_unittests', 'courgette_unittests', 116 'crypto_unittests', 'googleurl_unittests', 'gpu_unittests', 117 'installer_util_unittests', 'interactive_ui_tests', 'ipc_tests', 118 'jingle_unittests', 'layout-tests', 'media_unittests', 119 'mini_installer_test', 'nacl_ui_tests', 'net_unittests', 120 'printing_unittests', 'remoting_unittests', 'safe_browsing_tests', 121 'sync_unit_tests', 'sync_integration_tests', 122 'test_shell_tests', 'ui_tests', 'unit_tests']; 134 123 135 124 var RELOAD_REQUIRING_PARAMETERS = ['showAllRuns', 'group', 'testType']; … … 138 127 // 0 is where the count is length is stored. 1 is the value. 139 128 var RLE = { 140 LENGTH: 0, 141 VALUE: 1 142 } 143 144 // The server that hosts the builder results json files. 129 LENGTH: 0, 130 VALUE: 1 131 } 132 145 133 var TEST_RESULTS_SERVER = 'http://test-results.appspot.com/'; 146 134 147 /** 148 * @return {boolean} Whether the value represents a failing result. 149 */ 150 function isFailingResult(value) { 151 return 'FSTOCIZ'.indexOf(value) != -1; 152 } 153 154 /** 155 * Takes a key and a value and sets the currentState[key] = value iff key is 156 * a valid hash parameter and the value is a valid value for that key. Handles 157 * cross-dashboard parameters then falls back to calling 158 * handleValidHashParameter for dashboard-specific parameters. 159 * 160 * @return {boolean} Whether the key what inserted into the currentState. 161 */ 162 function handleValidHashParameterWrapper(key, value) { 163 switch(key) { 135 function isFailingResult(value) 136 { 137 return 'FSTOCIZ'.indexOf(value) != -1; 138 } 139 140 // Takes a key and a value and sets the g_currentState[key] = value iff key is 141 // a valid hash parameter and the value is a valid value for that key. Handles 142 // cross-dashboard parameters then falls back to calling 143 // handleValidHashParameter for dashboard-specific parameters. 144 // 145 // @return {boolean} Whether the key what inserted into the g_currentState. 146 function handleValidHashParameterWrapper(key, value) 147 { 148 switch(key) { 164 149 case 'testType': 165 validateParameter(currentState, key, value, 166 function() { 167 return TEST_TYPES.indexOf(value) != -1; 168 }); 169 return true; 150 validateParameter(g_currentState, key, value, 151 function() { return TEST_TYPES.indexOf(value) != -1; }); 152 return true; 170 153 171 154 case 'group': 172 validateParameter(currentState, key, value, 173 function() { 174 return value in LAYOUT_TESTS_BUILDER_GROUPS; 175 }); 176 return true; 155 validateParameter(g_currentState, key, value, 156 function() { return value in LAYOUT_TESTS_BUILDER_GROUPS; }); 157 return true; 177 158 178 159 // FIXME: remove support for this parameter once the waterfall starts to 179 160 // pass in the builder name instead. 180 161 case 'master': 181 validateParameter(currentState, key, value, 182 function() { 183 return value in LEGACY_BUILDER_MASTERS_TO_GROUPS; 184 }); 185 return true; 162 validateParameter(g_currentState, key, value, 163 function() { return value in LEGACY_BUILDER_MASTERS_TO_GROUPS; }); 164 return true; 186 165 187 166 case 'builder': 188 validateParameter(currentState, key, value, 189 function() { 190 return value in builders; 191 }); 192 return true; 167 validateParameter(g_currentState, key, value, 168 function() { return value in g_builders; }); 169 return true; 193 170 194 171 case 'useTestData': 195 172 case 'showAllRuns': 196 currentState[key] = value == 'true';197 return true;173 g_currentState[key] = value == 'true'; 174 return true; 198 175 199 176 case 'buildDir': 200 currentState['testType'] = 'layout-test-results'; 201 if (value === 'Debug' || value == 'Release') { 202 currentState[key] = value; 203 return true; 204 } else { 205 return false; 206 } 177 g_currentState['testType'] = 'layout-test-results'; 178 if (value === 'Debug' || value == 'Release') { 179 g_currentState[key] = value; 180 return true; 181 } else 182 return false; 207 183 208 184 default: 209 return handleValidHashParameter(key, value);210 }211 } 212 213 var defaultCrossDashboardStateValues = {214 group: '@DEPS - chromium.org',215 showAllRuns: false,216 testType: 'layout-tests',217 buildDir : ''185 return handleValidHashParameter(key, value); 186 } 187 } 188 189 var g_defaultCrossDashboardStateValues = { 190 group: '@DEPS - chromium.org', 191 showAllRuns: false, 192 testType: 'layout-tests', 193 buildDir : '' 218 194 } 219 195 220 196 // Generic utility functions. 221 function $(id) { 222 return document.getElementById(id); 223 } 224 225 function stringContains(a, b) { 226 return a.indexOf(b) != -1; 227 } 228 229 function caseInsensitiveContains(a, b) { 230 return a.match(new RegExp(b, 'i')); 231 } 232 233 function startsWith(a, b) { 234 return a.indexOf(b) == 0; 235 } 236 237 function endsWith(a, b) { 238 return a.lastIndexOf(b) == a.length - b.length; 239 } 240 241 function isValidName(str) { 242 return str.match(/[A-Za-z0-9\-\_,]/); 243 } 244 245 function trimString(str) { 246 return str.replace(/^\s+|\s+$/g, ''); 247 } 248 249 function request(url, success, error, opt_isBinaryData) { 250 console.log('XMLHttpRequest: ' + url); 251 var xhr = new XMLHttpRequest(); 252 xhr.open('GET', url, true); 253 if (opt_isBinaryData) 254 xhr.overrideMimeType('text/plain; charset=x-user-defined'); 255 xhr.onreadystatechange = function(e) { 256 if (xhr.readyState == 4) { 257 if (xhr.status == 200) 258 success(xhr); 259 else 260 error(xhr); 261 } 262 } 263 xhr.send(); 264 } 265 266 function validateParameter(state, key, value, validateFn) { 267 if (validateFn()) { 268 state[key] = value; 269 } else { 270 console.log(key + ' value is not valid: ' + value); 271 } 272 } 273 274 /** 275 * Parses window.location.hash and set the currentState values appropriately. 276 */ 277 function parseParameters(parameterStr) { 278 oldState = currentState; 279 currentState = {}; 280 281 var hash = window.location.hash; 282 var paramsList = hash ? hash.substring(1).split('&') : []; 283 var paramsMap = {}; 284 var invalidKeys = []; 285 for (var i = 0; i < paramsList.length; i++) { 286 var thisParam = paramsList[i].split('='); 287 if (thisParam.length != 2) { 288 console.log('Invalid query parameter: ' + paramsList[i]); 289 continue; 290 } 291 292 paramsMap[thisParam[0]] = decodeURIComponent(thisParam[1]); 293 } 294 295 function parseParam(key) { 296 var value = paramsMap[key]; 297 if (!handleValidHashParameterWrapper(key, value)) 298 invalidKeys.push(key + '=' + value); 299 } 300 301 // Parse builder param last, since the list of valid builders depends on the 302 // other parameters. 303 for (var key in paramsMap) { 304 if (key != 'builder') 305 parseParam(key); 306 } 307 if ('builder' in paramsMap) { 308 if (!builders) { 309 var tempState = {}; 310 for (var key in currentState) { 311 tempState[key] = currentState[key]; 312 } 313 fillMissingValues(tempState, defaultCrossDashboardStateValues); 314 fillMissingValues(tempState, defaultStateValues); 315 initBuilders(tempState); 316 } 317 parseParam('builder'); 318 } 319 320 if (invalidKeys.length) 321 console.log("Invalid query parameters: " + invalidKeys.join(',')); 322 323 var diffState = diffStates(); 324 325 fillMissingValues(currentState, defaultCrossDashboardStateValues); 326 fillMissingValues(currentState, defaultStateValues); 327 328 // Some parameters require loading different JSON files when the value changes. Do a reload. 329 if (oldState) { 330 for (var key in currentState) { 331 if (oldState[key] != currentState[key] && RELOAD_REQUIRING_PARAMETERS.indexOf(key) != -1) 332 window.location.reload(); 333 } 334 } 335 336 return diffState; 337 } 338 339 /** 340 * Find the difference of currentState with oldState. 341 * @return {Object} key:values of the new or changed params. 342 */ 343 function diffStates() { 344 // If there is no old state, everything in the current state is new. 345 if (!oldState) { 346 return currentState; 347 } 348 349 var changedParams = {}; 350 for (curKey in currentState) { 351 var oldVal = oldState[curKey]; 352 var newVal = currentState[curKey]; 353 // Add new keys or changed values. 354 if (!oldVal || oldVal != newVal) { 355 changedParams[curKey] = newVal; 356 } 357 } 358 return changedParams; 359 } 360 361 function getDefaultValue(key) { 362 if (key in defaultStateValues) 363 return defaultStateValues[key]; 364 return defaultCrossDashboardStateValues[key]; 365 } 366 367 function fillMissingValues(to, from) { 368 for (var state in from) { 369 if (!(state in to)) 370 to[state] = from[state]; 371 } 372 } 373 374 /** 375 * Load a script. 376 * @param {string} path Path to the script to load. 377 * @param {Function=} opt_onError Optional function to call if the script 378 * does not load. 379 * @param {Function=} opt_onLoad Optional function to call when the script 380 * is loaded. Called with the script element as its 1st argument. 381 */ 382 function appendScript(path, opt_onError, opt_onLoad) { 383 var script = document.createElement('script'); 384 script.src = path; 385 if (opt_onLoad) { 386 script.onreadystatechange = function() { 387 if (this.readyState == 'complete') opt_onLoad(script); 388 }; 389 script.onload = function() { opt_onLoad(script); }; 390 } 391 if (opt_onError) { 392 script.onerror = opt_onError; 393 } 394 document.getElementsByTagName('head')[0].appendChild(script); 197 function $(id) 198 { 199 return document.getElementById(id); 200 } 201 202 function stringContains(a, b) 203 { 204 return a.indexOf(b) != -1; 205 } 206 207 function caseInsensitiveContains(a, b) 208 { 209 return a.match(new RegExp(b, 'i')); 210 } 211 212 function startsWith(a, b) 213 { 214 return a.indexOf(b) == 0; 215 } 216 217 function endsWith(a, b) 218 { 219 return a.lastIndexOf(b) == a.length - b.length; 220 } 221 222 function isValidName(str) 223 { 224 return str.match(/[A-Za-z0-9\-\_,]/); 225 } 226 227 function trimString(str) 228 { 229 return str.replace(/^\s+|\s+$/g, ''); 230 } 231 232 function request(url, success, error, opt_isBinaryData) 233 { 234 console.log('XMLHttpRequest: ' + url); 235 var xhr = new XMLHttpRequest(); 236 xhr.open('GET', url, true); 237 if (opt_isBinaryData) 238 xhr.overrideMimeType('text/plain; charset=x-user-defined'); 239 xhr.onreadystatechange = function(e) { 240 if (xhr.readyState == 4) { 241 if (xhr.status == 200) 242 success(xhr); 243 else 244 error(xhr); 245 } 246 } 247 xhr.send(); 248 } 249 250 function validateParameter(state, key, value, validateFn) 251 { 252 if (validateFn()) 253 state[key] = value; 254 else 255 console.log(key + ' value is not valid: ' + value); 256 } 257 258 function parseParameters(parameterStr) 259 { 260 g_oldState = g_currentState; 261 g_currentState = {}; 262 263 var hash = window.location.hash; 264 var paramsList = hash ? hash.substring(1).split('&') : []; 265 var paramsMap = {}; 266 var invalidKeys = []; 267 for (var i = 0; i < paramsList.length; i++) { 268 var thisParam = paramsList[i].split('='); 269 if (thisParam.length != 2) { 270 console.log('Invalid query parameter: ' + paramsList[i]); 271 continue; 272 } 273 274 paramsMap[thisParam[0]] = decodeURIComponent(thisParam[1]); 275 } 276 277 function parseParam(key) 278 { 279 var value = paramsMap[key]; 280 if (!handleValidHashParameterWrapper(key, value)) 281 invalidKeys.push(key + '=' + value); 282 } 283 284 // Parse builder param last, since the list of valid builders depends on the other parameters. 285 for (var key in paramsMap) { 286 if (key != 'builder') 287 parseParam(key); 288 } 289 if ('builder' in paramsMap) { 290 if (!g_builders) { 291 var tempState = {}; 292 for (var key in g_currentState) 293 tempState[key] = g_currentState[key]; 294 fillMissingValues(tempState, g_defaultCrossDashboardStateValues); 295 fillMissingValues(tempState, g_defaultStateValues); 296 initBuilders(tempState); 297 } 298 parseParam('builder'); 299 } 300 301 if (invalidKeys.length) 302 console.log("Invalid query parameters: " + invalidKeys.join(',')); 303 304 var diffState = diffStates(); 305 306 fillMissingValues(g_currentState, g_defaultCrossDashboardStateValues); 307 fillMissingValues(g_currentState, g_defaultStateValues); 308 309 // Some parameters require loading different JSON files when the value changes. Do a reload. 310 if (g_oldState) { 311 for (var key in g_currentState) { 312 if (g_oldState[key] != g_currentState[key] && RELOAD_REQUIRING_PARAMETERS.indexOf(key) != -1) 313 window.location.reload(); 314 } 315 } 316 317 return diffState; 318 } 319 320 // Find the difference of g_currentState with g_oldState. 321 // @return {Object} key:values of the new or changed params. 322 function diffStates() 323 { 324 // If there is no old state, everything in the current state is new. 325 if (!g_oldState) 326 return g_currentState; 327 328 var changedParams = {}; 329 for (curKey in g_currentState) { 330 var oldVal = g_oldState[curKey]; 331 var newVal = g_currentState[curKey]; 332 // Add new keys or changed values. 333 if (!oldVal || oldVal != newVal) 334 changedParams[curKey] = newVal; 335 } 336 return changedParams; 337 } 338 339 function getDefaultValue(key) 340 { 341 if (key in g_defaultStateValues) 342 return g_defaultStateValues[key]; 343 return g_defaultCrossDashboardStateValues[key]; 344 } 345 346 function fillMissingValues(to, from) 347 { 348 for (var state in from) { 349 if (!(state in to)) 350 to[state] = from[state]; 351 } 352 } 353 354 // Load a script. 355 // @param {string} path Path to the script to load. 356 // @param {Function=} opt_onError Optional function to call if the script 357 // does not load. 358 // @param {Function=} opt_onLoad Optional function to call when the script 359 // is loaded. Called with the script element as its 1st argument. 360 function appendScript(path, opt_onError, opt_onLoad) 361 { 362 var script = document.createElement('script'); 363 script.src = path; 364 if (opt_onLoad) { 365 script.onreadystatechange = function() { 366 if (this.readyState == 'complete') 367 opt_onLoad(script); 368 }; 369 script.onload = function() { opt_onLoad(script); }; 370 } 371 if (opt_onError) 372 script.onerror = opt_onError; 373 document.getElementsByTagName('head')[0].appendChild(script); 395 374 } 396 375 397 376 // Permalinkable state of the page. 398 var currentState;399 400 // Saved value of previous currentState. This is used to detect changing from377 var g_currentState; 378 379 // Saved value of previous g_currentState. This is used to detect changing from 401 380 // one set of builders to another, which requires reloading the page. 402 var oldState;381 var g_oldState; 403 382 404 383 // Parse cross-dashboard parameters before using them. 405 384 parseParameters(); 406 385 407 function isLayoutTestResults() { 408 return currentState.testType == 'layout-tests'; 409 } 410 411 function getCurrentBuilderGroup(opt_state) { 412 var state = opt_state || currentState; 413 switch (state.testType) { 386 function isLayoutTestResults() 387 { 388 return g_currentState.testType == 'layout-tests'; 389 } 390 391 function getCurrentBuilderGroup(opt_state) 392 { 393 var state = opt_state || g_currentState; 394 switch (state.testType) { 414 395 case 'layout-tests': 415 return LAYOUT_TESTS_BUILDER_GROUPS[state.group]416 break;396 return LAYOUT_TESTS_BUILDER_GROUPS[state.group] 397 break; 417 398 case 'app_unittests': 418 399 case 'base_unittests': … … 439 420 case 'ui_tests': 440 421 case 'unit_tests': 441 return G_TESTS_BUILDER_GROUP;442 break;422 return G_TESTS_BUILDER_GROUP; 423 break; 443 424 default: 444 console.log('invalid testType parameter: ' + state.testType); 445 } 446 } 447 448 function getBuilderMaster(builderName) { 449 return BUILDER_TO_MASTER[builderName]; 450 } 451 452 function isTipOfTreeWebKitBuilder() { 453 return getCurrentBuilderGroup().isToTWebKit; 454 } 455 456 var defaultBuilderName, builders, expectationsBuilder; 457 function initBuilders(state) { 458 if (state.buildDir) { 459 // If buildDir is set, point to the results.json and expectations.json in the 460 // local tree. Useful for debugging changes to the python JSON generator. 461 defaultBuilderName = 'DUMMY_BUILDER_NAME'; 462 builders = {'DUMMY_BUILDER_NAME': ''}; 463 var loc = document.location.toString(); 464 var offset = loc.indexOf('webkit/'); 465 } else { 466 // FIXME: remove support for mapping from the master parameter to the group 467 // one once the waterfall starts to pass in the builder name instead. 468 if (state.master) { 469 state.group = LEGACY_BUILDER_MASTERS_TO_GROUPS[state.master]; 470 window.location.hash = window.location.hash.replace('master=' + state.master, 'group=' + state.group); 471 delete state.master; 472 } 473 getCurrentBuilderGroup(state).setup(); 474 } 475 } 476 initBuilders(currentState); 425 console.log('invalid testType parameter: ' + state.testType); 426 } 427 } 428 429 function getBuilderMaster(builderName) 430 { 431 return BUILDER_TO_MASTER[builderName]; 432 } 433 434 function isTipOfTreeWebKitBuilder() 435 { 436 return getCurrentBuilderGroup().isToTWebKit; 437 } 438 439 var g_defaultBuilderName, g_builders, g_expectationsBuilder; 440 function initBuilders(state) 441 { 442 if (state.buildDir) { 443 // If buildDir is set, point to the results.json and expectations.json in the 444 // local tree. Useful for debugging changes to the python JSON generator. 445 g_defaultBuilderName = 'DUMMY_BUILDER_NAME'; 446 g_builders = {'DUMMY_BUILDER_NAME': ''}; 447 var loc = document.location.toString(); 448 var offset = loc.indexOf('webkit/'); 449 } else { 450 // FIXME: remove support for mapping from the master parameter to the group 451 // one once the waterfall starts to pass in the builder name instead. 452 if (state.master) { 453 state.group = LEGACY_BUILDER_MASTERS_TO_GROUPS[state.master]; 454 window.location.hash = window.location.hash.replace('master=' + state.master, 'group=' + state.group); 455 delete state.master; 456 } 457 getCurrentBuilderGroup(state).setup(); 458 } 459 } 460 initBuilders(g_currentState); 477 461 478 462 // Append JSON script elements. 479 var resultsByBuilder = {}; 480 var expectationsByTest = {}; 481 function ADD_RESULTS(builds) { 482 for (var builderName in builds) { 483 if (builderName != 'version') 484 resultsByBuilder[builderName] = builds[builderName]; 485 } 486 487 handleResourceLoad(); 488 } 489 490 function getPathToBuilderResultsFile(builderName) { 491 return TEST_RESULTS_SERVER + 'testfile?builder=' + builderName + 492 '&master=' + getBuilderMaster(builderName).name + 493 '&testtype=' + currentState.testType + '&name='; 463 var g_resultsByBuilder = {}; 464 var g_expectationsByTest = {}; 465 function ADD_RESULTS(builds) 466 { 467 for (var builderName in builds) { 468 if (builderName != 'version') 469 g_resultsByBuilder[builderName] = builds[builderName]; 470 } 471 472 handleResourceLoad(); 473 } 474 475 function getPathToBuilderResultsFile(builderName) 476 { 477 return TEST_RESULTS_SERVER + 'testfile?builder=' + builderName + 478 '&master=' + getBuilderMaster(builderName).name + 479 '&testtype=' + g_currentState.testType + '&name='; 494 480 } 495 481 496 482 // Only webkit tests have a sense of test expectations. 497 var waitingOnExpectations = isLayoutTestResults() && !isTreeMap(); 498 if (waitingOnExpectations) { 499 function ADD_EXPECTATIONS(expectations) { 500 waitingOnExpectations = false; 501 expectationsByTest = expectations; 483 var g_waitingOnExpectations = isLayoutTestResults() && !isTreeMap(); 484 if (g_waitingOnExpectations) { 485 function ADD_EXPECTATIONS(expectations) 486 { 487 g_waitingOnExpectations = false; 488 g_expectationsByTest = expectations; 489 handleResourceLoad(); 490 } 491 } 492 493 function isTreeMap() 494 { 495 return endsWith(window.location.pathname, 'treemap.html'); 496 } 497 498 function appendJSONScriptElementFor(builderName) 499 { 500 var resultsFilename; 501 if (isTreeMap()) 502 resultsFilename = 'times_ms.json'; 503 else if (g_currentState.showAllRuns) 504 resultsFilename = 'results.json'; 505 else 506 resultsFilename = 'results-small.json'; 507 508 appendScript(getPathToBuilderResultsFile(builderName) + resultsFilename, 509 partial(handleResourceLoadError, builderName), 510 partial(handleScriptLoaded, builderName)); 511 } 512 513 function appendJSONScriptElements() 514 { 515 clearErrors(); 516 517 if (isTreeMap()) 518 return; 519 520 parseParameters(); 521 522 if (g_currentState.useTestData) { 523 appendScript('flakiness_dashboard_tests.js'); 524 return; 525 } 526 527 for (var builderName in g_builders) 528 appendJSONScriptElementFor(builderName); 529 530 // Grab expectations file from the fastest builder, which is Linux release 531 // right now. Could be changed to any other builder if needed. 532 if (g_waitingOnExpectations) 533 appendScript(getPathToBuilderResultsFile(g_expectationsBuilder) + 'expectations.json'); 534 } 535 536 var g_hasDoneInitialPageGeneration = false; 537 // String of error messages to display to the user. 538 var g_errorMessages = ''; 539 540 function handleResourceLoad() 541 { 542 // In case we load a results.json that's not in the list of builders, 543 // make sure to only call handleLocationChange once from the resource loads. 544 if (!g_hasDoneInitialPageGeneration) 545 handleLocationChange(); 546 } 547 548 function handleScriptLoaded(builderName, script) 549 { 550 // We need this work-around for webkit.org/b/50589. 551 if (!g_resultsByBuilder[builderName]) { 552 var error = new Error("Builder data was empty"); 553 error.target = script; 554 handleResourceLoadError(builderName, error); 555 } 556 } 557 558 // Handle resource loading errors - 404s, 500s, etc. Recover from the error to 559 // still show as much data as possible, but show some UI about the failure, and 560 // do not try using this resource again until user refreshes. 561 // 562 // @param {string} builderName Name of builder that the resource failed for. 563 // @param {Event} e The error event. 564 function handleResourceLoadError(builderName, e) 565 { 566 var error = e.target.src + ' failed to load for ' + builderName + '.'; 567 568 if (isLayoutTestResults()) { 569 console.error(error); 570 addError(error); 571 } else { 572 // Avoid to show error/warning messages for non-layout tests. We may be 573 // checking the builders that are not running the tests. 574 console.info('info:' + error); 575 } 576 577 // Remove this builder from builders, so we don't try to use the 578 // data that isn't there. 579 delete g_builders[builderName]; 580 581 // Change the default builder name if it has been deleted. 582 if (g_defaultBuilderName == builderName) { 583 g_defaultBuilderName = null; 584 for (var availableBuilderName in g_builders) { 585 g_defaultBuilderName = availableBuilderName; 586 g_defaultStateValues.builder = availableBuilderName; 587 break; 588 } 589 if (!g_defaultBuilderName) { 590 var error = 'No tests results found for ' + g_currentState.testType + '. Reload the page to try fetching it again.'; 591 console.error(error); 592 addError(error); 593 } 594 } 595 596 // Proceed as if the resource had loaded. 502 597 handleResourceLoad(); 503 } 504 } 505 506 function isTreeMap() { 507 return endsWith(window.location.pathname, 'treemap.html'); 508 } 509 510 function appendJSONScriptElementFor(builderName) { 511 var resultsFilename; 512 if (isTreeMap()) 513 resultsFilename = 'times_ms.json'; 514 else if (currentState.showAllRuns) 515 resultsFilename = 'results.json'; 516 else 517 resultsFilename = 'results-small.json'; 518 519 appendScript(getPathToBuilderResultsFile(builderName) + resultsFilename, 520 partial(handleResourceLoadError, builderName), 521 partial(handleScriptLoaded, builderName)); 522 } 523 524 function appendJSONScriptElements() { 525 clearErrors(); 526 527 if (isTreeMap()) 528 return; 529 530 parseParameters(); 531 532 if (currentState.useTestData) { 533 appendScript('flakiness_dashboard_tests.js'); 534 return; 535 } 536 537 for (var builderName in builders) { 538 appendJSONScriptElementFor(builderName); 539 } 540 541 // Grab expectations file from the fastest builder, which is Linux release 542 // right now. Could be changed to any other builder if needed. 543 if (waitingOnExpectations) { 544 appendScript(getPathToBuilderResultsFile(expectationsBuilder) + 545 'expectations.json'); 546 } 547 } 548 549 var hasDoneInitialPageGeneration = false; 550 // String of error messages to display to the user. 551 var errorMessages = ''; 552 553 function handleResourceLoad() { 554 // In case we load a results.json that's not in the list of builders, 555 // make sure to only call handleLocationChange once from the resource loads. 556 if (!hasDoneInitialPageGeneration) 557 handleLocationChange(); 558 } 559 560 function handleScriptLoaded(builderName, script) { 561 // We need this work-around for webkit.org/b/50589. 562 if (!resultsByBuilder[builderName]) { 563 var error = new Error("Builder data was empty"); 564 error.target = script; 565 handleResourceLoadError(builderName, error); 566 } 567 } 568 569 /** 570 * Handle resource loading errors - 404s, 500s, etc. Recover from the error to 571 * still show as much data as possible, but show some UI about the failure, and 572 * do not try using this resource again until user refreshes. 573 * 574 * @param {string} builderName Name of builder that the resource failed for. 575 * @param {Event} e The error event. 576 */ 577 function handleResourceLoadError(builderName, e) { 578 var error = e.target.src + ' failed to load for ' + builderName + '.'; 579 580 if (isLayoutTestResults()) { 581 console.error(error); 582 addError(error); 583 } else { 584 // Avoid to show error/warning messages for non-layout tests. We may be 585 // checking the builders that are not running the tests. 586 console.info('info:' + error); 587 } 588 589 // Remove this builder from builders, so we don't try to use the 590 // data that isn't there. 591 delete builders[builderName]; 592 593 // Change the default builder name if it has been deleted. 594 if (defaultBuilderName == builderName) { 595 defaultBuilderName = null; 596 for (var availableBuilderName in builders) { 597 defaultBuilderName = availableBuilderName; 598 defaultStateValues.builder = availableBuilderName; 599 break; 600 } 601 if (!defaultBuilderName) { 602 var error = 'No tests results found for ' + currentState.testType + 603 '. Reload the page to try fetching it again.'; 604 console.error(error); 605 addError(error); 606 } 607 } 608 609 // Proceed as if the resource had loaded. 610 handleResourceLoad(); 611 } 612 613 614 /** 615 * Record a new error message. 616 * @param {string} errorMsg The message to show to the user. 617 */ 618 function addError(errorMsg) { 619 errorMessages += errorMsg + '<br />'; 620 } 621 622 /** 623 * Clear out error and warning messages. 624 */ 625 function clearErrors() { 626 errorMessages = ''; 627 } 628 629 /** 630 * If there are errors, show big and red UI for errors so as to be noticed. 631 */ 632 function showErrors() { 633 var errors = $('errors'); 634 635 if (!errorMessages) { 636 if (errors) 637 errors.parentNode.removeChild(errors); 638 return; 639 } 640 641 if (!errors) { 642 errors = document.createElement('H2'); 643 errors.style.color = 'red'; 644 errors.id = 'errors'; 645 document.body.appendChild(errors); 646 } 647 648 errors.innerHTML = errorMessages; 649 } 650 651 /** 652 * @return {boolean} Whether the json files have all completed loading. 653 */ 654 function haveJsonFilesLoaded() { 655 if (waitingOnExpectations) 656 return false; 657 658 if (isTreeMap()) 598 } 599 600 601 // Record a new error message. 602 // @param {string} errorMsg The message to show to the user. 603 function addError(errorMsg) 604 { 605 g_errorMessages += errorMsg + '<br />'; 606 } 607 608 // Clear out error and warning messages. 609 function clearErrors() 610 { 611 g_errorMessages = ''; 612 } 613 614 // If there are errors, show big and red UI for errors so as to be noticed. 615 function showErrors() 616 { 617 var errors = $('errors'); 618 619 if (!g_errorMessages) { 620 if (errors) 621 errors.parentNode.removeChild(errors); 622 return; 623 } 624 625 if (!errors) { 626 errors = document.createElement('H2'); 627 errors.style.color = 'red'; 628 errors.id = 'errors'; 629 document.body.appendChild(errors); 630 } 631 632 errors.innerHTML = g_errorMessages; 633 } 634 635 // @return {boolean} Whether the json files have all completed loading. 636 function haveJsonFilesLoaded() 637 { 638 if (g_waitingOnExpectations) 639 return false; 640 641 if (isTreeMap()) 642 return true; 643 644 for (var builder in g_builders) { 645 if (!g_resultsByBuilder[builder]) 646 return false; 647 } 659 648 return true; 660 661 for (var builder in builders) { 662 if (!resultsByBuilder[builder]) 663 return false; 664 } 665 return true; 666 } 667 668 function handleLocationChange() { 669 if(!haveJsonFilesLoaded()) { 670 return; 671 } 672 673 hasDoneInitialPageGeneration = true; 674 675 var params = parseParameters(); 676 var shouldGeneratePage = true; 677 if (Object.keys(params).length) 678 shouldGeneratePage = handleQueryParameterChange(params); 679 680 var newHash = getPermaLinkURLHash(); 681 var winHash = window.location.hash || "#"; 682 // Make sure the location is the same as the state we are using internally. 683 // These get out of sync if processQueryParamChange changed state. 684 if (newHash != winHash) { 685 // This will cause another hashchange, and when we loop 686 // back through here next time, we'll go through generatePage. 687 window.location.hash = newHash; 688 } else if (shouldGeneratePage) { 689 generatePage(); 690 } 649 } 650 651 function handleLocationChange() 652 { 653 if(!haveJsonFilesLoaded()) 654 return; 655 656 g_hasDoneInitialPageGeneration = true; 657 658 var params = parseParameters(); 659 var shouldGeneratePage = true; 660 if (Object.keys(params).length) 661 shouldGeneratePage = handleQueryParameterChange(params); 662 663 var newHash = getPermaLinkURLHash(); 664 var winHash = window.location.hash || "#"; 665 // Make sure the location is the same as the state we are using internally. 666 // These get out of sync if processQueryParamChange changed state. 667 if (newHash != winHash) { 668 // This will cause another hashchange, and when we loop 669 // back through here next time, we'll go through generatePage. 670 window.location.hash = newHash; 671 } else if (shouldGeneratePage) 672 generatePage(); 691 673 } 692 674 693 675 window.onhashchange = handleLocationChange; 694 676 695 /** 696 * Sets the page state. Takes varargs of key, value pairs. 697 */ 698 function setQueryParameter(var_args) { 699 var state = Object.create(currentState); 700 for (var i = 0; i < arguments.length; i += 2) { 701 var key = arguments[i]; 702 state[key] = arguments[i + 1]; 703 } 704 // Note: We use window.location.hash rather that window.location.replace 705 // because of bugs in Chrome where extra entries were getting created 706 // when back button was pressed and full page navigation was occuring. 707 // TODO: file those bugs. 708 window.location.hash = getPermaLinkURLHash(state); 709 } 710 711 function getPermaLinkURLHash(opt_state) { 712 var state = opt_state || currentState; 713 return '#' + joinParameters(state); 714 } 715 716 function joinParameters(stateObject) { 717 var state = []; 718 for (var key in stateObject) { 719 var value = stateObject[key]; 720 if (value != getDefaultValue(key)) 721 state.push(key + '=' + encodeURIComponent(value)); 722 } 723 return state.join('&'); 724 } 725 726 function logTime(msg, startTime) { 727 console.log(msg + ': ' + (Date.now() - startTime)); 728 } 729 730 function hidePopup() { 731 var popup = $('popup'); 732 if (popup) 733 popup.parentNode.removeChild(popup); 734 } 735 736 function showPopup(e, html) { 737 var popup = $('popup'); 738 if (!popup) { 739 popup = document.createElement('div'); 740 popup.id = 'popup'; 741 document.body.appendChild(popup); 742 } 743 744 // Set html first so that we can get accurate size metrics on the popup. 745 popup.innerHTML = html; 746 747 var targetRect = e.target.getBoundingClientRect(); 748 749 var x = Math.min(targetRect.left - 10, 750 document.documentElement.clientWidth - popup.offsetWidth); 751 x = Math.max(0, x); 752 popup.style.left = x + document.body.scrollLeft + 'px'; 753 754 var y = targetRect.top + targetRect.height; 755 if (y + popup.offsetHeight > document.documentElement.clientHeight) { 756 y = targetRect.top - popup.offsetHeight; 757 } 758 y = Math.max(0, y); 759 popup.style.top = y + document.body.scrollTop + 'px'; 760 } 761 762 /** 763 * Create a new function with some of its arguements 764 * pre-filled. 765 * Taken from goog.partial in the Closure library. 766 * @param {Function} fn A function to partially apply. 767 * @param {...*} var_args Additional arguments that are partially 768 * applied to fn. 769 * @return {!Function} A partially-applied form of the function bind() was 770 * invoked as a method of. 771 */ 772 function partial(fn, var_args) { 773 var args = Array.prototype.slice.call(arguments, 1); 774 return function() { 775 // Prepend the bound arguments to the current arguments. 776 var newArgs = Array.prototype.slice.call(arguments); 777 newArgs.unshift.apply(newArgs, args); 778 return fn.apply(this, newArgs); 779 }; 677 // Sets the page state. Takes varargs of key, value pairs. 678 function setQueryParameter(var_args) 679 { 680 var state = Object.create(g_currentState); 681 for (var i = 0; i < arguments.length; i += 2) { 682 var key = arguments[i]; 683 state[key] = arguments[i + 1]; 684 } 685 // Note: We use window.location.hash rather that window.location.replace 686 // because of bugs in Chrome where extra entries were getting created 687 // when back button was pressed and full page navigation was occuring. 688 // TODO: file those bugs. 689 window.location.hash = getPermaLinkURLHash(state); 690 } 691 692 function getPermaLinkURLHash(opt_state) 693 { 694 var state = opt_state || g_currentState; 695 return '#' + joinParameters(state); 696 } 697 698 function joinParameters(stateObject) 699 { 700 var state = []; 701 for (var key in stateObject) { 702 var value = stateObject[key]; 703 if (value != getDefaultValue(key)) 704 state.push(key + '=' + encodeURIComponent(value)); 705 } 706 return state.join('&'); 707 } 708 709 function logTime(msg, startTime) 710 { 711 console.log(msg + ': ' + (Date.now() - startTime)); 712 } 713 714 function hidePopup() 715 { 716 var popup = $('popup'); 717 if (popup) 718 popup.parentNode.removeChild(popup); 719 } 720 721 function showPopup(e, html) 722 { 723 var popup = $('popup'); 724 if (!popup) { 725 popup = document.createElement('div'); 726 popup.id = 'popup'; 727 document.body.appendChild(popup); 728 } 729 730 // Set html first so that we can get accurate size metrics on the popup. 731 popup.innerHTML = html; 732 733 var targetRect = e.target.getBoundingClientRect(); 734 735 var x = Math.min(targetRect.left - 10, document.documentElement.clientWidth - popup.offsetWidth); 736 x = Math.max(0, x); 737 popup.style.left = x + document.body.scrollLeft + 'px'; 738 739 var y = targetRect.top + targetRect.height; 740 if (y + popup.offsetHeight > document.documentElement.clientHeight) 741 y = targetRect.top - popup.offsetHeight; 742 y = Math.max(0, y); 743 popup.style.top = y + document.body.scrollTop + 'px'; 744 } 745 746 // Create a new function with some of its arguements 747 // pre-filled. 748 // Taken from goog.partial in the Closure library. 749 // @param {Function} fn A function to partially apply. 750 // @param {...*} var_args Additional arguments that are partially 751 // applied to fn. 752 // @return {!Function} A partially-applied form of the function bind() was 753 // invoked as a method of. 754 function partial(fn, var_args) 755 { 756 var args = Array.prototype.slice.call(arguments, 1); 757 return function() { 758 // Prepend the bound arguments to the current arguments. 759 var newArgs = Array.prototype.slice.call(arguments); 760 newArgs.unshift.apply(newArgs, args); 761 return fn.apply(this, newArgs); 762 }; 780 763 }; 781 764 782 /** 783 * Returns the keys of the object/map/hash. 784 * Taken from goog.object.getKeys in the Closure library. 785 * 786 * @param {Object} obj The object from which to get the keys. 787 * @return {!Array.<string>} Array of property keys. 788 */ 789 function getKeys(obj) { 790 var res = []; 791 for (var key in obj) { 792 res.push(key); 793 } 794 return res; 795 } 796 797 /** 798 * Returns the appropriate expectatiosn map for the current testType. 799 */ 800 function getExpectationsMap() { 801 return isLayoutTestResults() ? LAYOUT_TEST_EXPECTATIONS_MAP_ : 802 GTEST_EXPECTATIONS_MAP_; 803 } 804 805 function toggleQueryParameter(param) { 806 setQueryParameter(param, !currentState[param]); 807 } 808 809 function checkboxHTML(queryParameter, label, isChecked, opt_extraJavaScript) { 810 var js = opt_extraJavaScript || ''; 811 return '<label style="padding-left: 2em">' + 812 '<input type="checkbox" onchange="toggleQueryParameter(\'' + queryParameter + '\');' + js + '" ' + 813 (isChecked ? 'checked' : '') + '>' + label + 814 '</label>'; 815 } 816 817 function selectHTML(label, queryParameter, options) { 818 var html = '<label style="padding-left: 2em">' + 819 label + ': ' + 820 '<select onchange="setQueryParameter(\'' + 821 queryParameter + '\', this[this.selectedIndex].value)">'; 822 823 for (var i = 0; i < options.length; i++) { 824 var value = options[i]; 825 html += '<option value="' + value + '" ' + 826 (currentState[queryParameter] == value ? 'selected' : '') + 827 '>' + value + '</option>' 828 } 829 html += '</select><label>'; 830 return html; 831 } 832 833 /** 834 * Returns the HTML for the select element to switch to different testTypes. 835 */ 836 function getHTMLForTestTypeSwitcher(opt_noBuilderMenu, opt_extraHtml, opt_includeNoneBuilder) { 837 var html = '<div style="border-bottom:1px dashed">'; 838 html += '' + 839 htmlForDashboardLink('Stats', 'aggregate_results.html') + 840 htmlForDashboardLink('Timeline', 'timeline_explorer.html') + 841 htmlForDashboardLink('Results', 'flakiness_dashboard.html') + 842 htmlForDashboardLink('Treemap', 'treemap.html'); 843 844 html += selectHTML('Test type', 'testType', TEST_TYPES); 845 846 if (!opt_noBuilderMenu) { 847 var buildersForMenu = Object.keys(builders); 848 if (opt_includeNoneBuilder) 849 buildersForMenu.unshift('--------------'); 850 html += selectHTML('Builder', 'builder', buildersForMenu); 851 } 852 853 if (isLayoutTestResults()) { 854 html += selectHTML('Group', 'group', getKeys(LAYOUT_TESTS_BUILDER_GROUPS)); 855 } 856 857 if (!isTreeMap()) { 858 html += checkboxHTML('showAllRuns', 'Show all runs', currentState.showAllRuns); 859 } 860 861 if (opt_extraHtml) { 862 html += opt_extraHtml; 863 } 864 return html + '</div>'; 865 } 866 867 function selectBuilder(builder) { 868 setQueryParameter('builder', builder); 869 } 870 871 function loadDashboard(fileName) { 872 var pathName = window.location.pathname; 873 pathName = pathName.substring(0, pathName.lastIndexOf('/') + 1); 874 window.location = pathName + fileName + window.location.hash; 875 } 876 877 function htmlForTopLink(html, onClick, isSelected) { 878 var cssText = isSelected ? 'font-weight: bold;' : 879 'color:blue;text-decoration:underline;cursor:pointer;'; 880 cssText += 'margin: 0 5px;'; 881 return '<span style="' + cssText + 882 '" onclick="' + onClick + '">' + html + '</span>'; 883 } 884 885 function htmlForDashboardLink(html, fileName) { 886 var pathName = window.location.pathname; 887 var currentFileName = pathName.substring(pathName.lastIndexOf('/') + 1); 888 var isSelected = currentFileName == fileName; 889 var onClick = 'loadDashboard(\'' + fileName + '\')'; 890 return htmlForTopLink(html, onClick, isSelected); 891 } 892 893 function getRevisionLink(results, index, key, singleUrlTemplate, rangeUrlTemplate) { 894 var currentRevision = parseInt(results[key][index], 10); 895 var previousRevision = parseInt(results[key][index + 1], 10); 896 897 function getSingleUrl() { 898 return singleUrlTemplate.replace('<rev>', currentRevision); 899 } 900 901 function getRangeUrl() { 902 return rangeUrlTemplate.replace('<rev1>', currentRevision). 903 replace('<rev2>', previousRevision + 1); 904 } 905 906 if (currentRevision == previousRevision) { 907 return 'At <a href="' + getSingleUrl() + '">r' + currentRevision + '</a>'; 908 } else if (currentRevision - previousRevision == 1) { 909 return '<a href="' + getSingleUrl() + '">r' + currentRevision + '</a>'; 910 } else { 911 return '<a href="' + getRangeUrl() + '">r' + 912 (previousRevision + 1) + ' to r' + 913 currentRevision + '</a>'; 914 } 915 } 916 917 function getChromiumRevisionLink(results, index) { 918 return getRevisionLink( 919 results, 920 index, 921 CHROME_REVISIONS_KEY, 922 'http://src.chromium.org/viewvc/chrome?view=rev&revision=<rev>', 923 'http://build.chromium.org/f/chromium/perf/dashboard/ui/changelog.html?url=/trunk/src&range=<rev2>:<rev1>&mode=html'); 924 } 925 926 function getWebKitRevisionLink(results, index) { 927 return getRevisionLink( 928 results, 929 index, 930 WEBKIT_REVISIONS_KEY, 931 'http://trac.webkit.org/changeset/<rev>', 932 'http://trac.webkit.org/log/trunk/?rev=<rev1>&stop_rev=<rev2>&limit=100&verbose=on'); 933 } 934 935 /** 936 * "Decompresses" the RLE-encoding of test results so that we can query it 937 * by build index and test name. 938 * 939 * @param {Object} results results for the current builder 940 * @return Object with these properties: 941 * - testNames: array mapping test index to test names. 942 * - resultsByBuild: array of builds, for each build a (sparse) array of test 943 * results by test index. 944 * - flakyTests: array with the boolean value true at test indices that are 945 * considered flaky (more than one single-build failure). 946 * - flakyDeltasByBuild: array of builds, for each build a count of flaky 947 * test results by expectation, as well as a total. 948 */ 949 function getTestResultsByBuild(builderResults) { 950 var builderTestResults = builderResults[TESTS_KEY]; 951 var buildCount = builderResults[FIXABLE_COUNTS_KEY].length; 952 var testResultsByBuild = new Array(buildCount); 953 var flakyDeltasByBuild = new Array(buildCount); 954 955 // Pre-sizing the test result arrays for each build saves us ~250ms 956 var testCount = 0; 957 for (var testName in builderTestResults) { 958 testCount++; 959 } 960 for (var i = 0; i < buildCount; i++) { 961 testResultsByBuild[i] = new Array(testCount); 962 testResultsByBuild[i][testCount - 1] = undefined; 963 964 flakyDeltasByBuild[i] = {}; 965 } 966 967 // Using indices instead of the full test names for each build saves us 968 // ~1500ms 969 var testIndex = 0; 970 var testNames = new Array(testCount); 971 var flakyTests = new Array(testCount); 972 973 // Decompress and "invert" test results (by build instead of by test) and 974 // determine which are flaky. 975 for (var testName in builderTestResults) { 976 var oneBuildFailureCount = 0; 977 978 testNames[testIndex] = testName; 979 var testResults = builderTestResults[testName].results; 980 for (var i = 0, rleResult, currentBuildIndex = 0; 981 (rleResult = testResults[i]) && currentBuildIndex < buildCount; 982 i++) { 983 var count = rleResult[RLE.LENGTH]; 984 var value = rleResult[RLE.VALUE]; 985 986 if (count == 1 && value in FAILURE_EXPECTATIONS_) { 987 oneBuildFailureCount++; 988 } 989 990 for (var j = 0; j < count; j++) { 991 testResultsByBuild[currentBuildIndex++][testIndex] = value; 992 if (currentBuildIndex == buildCount) { 993 break; 765 // Returns the keys of the object/map/hash. 766 // Taken from goog.object.getKeys in the Closure library. 767 // 768 // @param {Object} obj The object from which to get the keys. 769 // @return {!Array.<string>} Array of property keys. 770 function getKeys(obj) 771 { 772 var res = []; 773 for (var key in obj) 774 res.push(key); 775 return res; 776 } 777 778 // Returns the appropriate expectatiosn map for the current testType. 779 function getExpectationsMap() 780 { 781 return isLayoutTestResults() ? LAYOUT_TEST_EXPECTATIONS_MAP_ : GTEST_EXPECTATIONS_MAP_; 782 } 783 784 function toggleQueryParameter(param) 785 { 786 setQueryParameter(param, !g_currentState[param]); 787 } 788 789 function checkboxHTML(queryParameter, label, isChecked, opt_extraJavaScript) 790 { 791 var js = opt_extraJavaScript || ''; 792 return '<label style="padding-left: 2em">' + 793 '<input type="checkbox" onchange="toggleQueryParameter(\'' + queryParameter + '\');' + js + '" ' + 794 (isChecked ? 'checked' : '') + '>' + label + 795 '</label>'; 796 } 797 798 function selectHTML(label, queryParameter, options) 799 { 800 var html = '<label style="padding-left: 2em">' + label + ': ' + 801 '<select onchange="setQueryParameter(\'' + queryParameter + '\', this[this.selectedIndex].value)">'; 802 803 for (var i = 0; i < options.length; i++) { 804 var value = options[i]; 805 html += '<option value="' + value + '" ' + 806 (g_currentState[queryParameter] == value ? 'selected' : '') + 807 '>' + value + '</option>' 808 } 809 html += '</select><label>'; 810 return html; 811 } 812 813 // Returns the HTML for the select element to switch to different testTypes. 814 function getHTMLForTestTypeSwitcher(opt_noBuilderMenu, opt_extraHtml, opt_includeNoneBuilder) 815 { 816 var html = '<div style="border-bottom:1px dashed">'; 817 html += '' + 818 htmlForDashboardLink('Stats', 'aggregate_results.html') + 819 htmlForDashboardLink('Timeline', 'timeline_explorer.html') + 820 htmlForDashboardLink('Results', 'flakiness_dashboard.html') + 821 htmlForDashboardLink('Treemap', 'treemap.html'); 822 823 html += selectHTML('Test type', 'testType', TEST_TYPES); 824 825 if (!opt_noBuilderMenu) { 826 var buildersForMenu = Object.keys(g_builders); 827 if (opt_includeNoneBuilder) 828 buildersForMenu.unshift('--------------'); 829 html += selectHTML('Builder', 'builder', buildersForMenu); 830 } 831 832 if (isLayoutTestResults()) 833 html += selectHTML('Group', 'group', getKeys(LAYOUT_TESTS_BUILDER_GROUPS)); 834 835 if (!isTreeMap()) 836 html += checkboxHTML('showAllRuns', 'Show all runs', g_currentState.showAllRuns); 837 838 if (opt_extraHtml) 839 html += opt_extraHtml; 840 return html + '</div>'; 841 } 842 843 function selectBuilder(builder) 844 { 845 setQueryParameter('builder', builder); 846 } 847 848 function loadDashboard(fileName) 849 { 850 var pathName = window.location.pathname; 851 pathName = pathName.substring(0, pathName.lastIndexOf('/') + 1); 852 window.location = pathName + fileName + window.location.hash; 853 } 854 855 function htmlForTopLink(html, onClick, isSelected) 856 { 857 var cssText = isSelected ? 'font-weight: bold;' : 'color:blue;text-decoration:underline;cursor:pointer;'; 858 cssText += 'margin: 0 5px;'; 859 return '<span style="' + cssText + '" onclick="' + onClick + '">' + html + '</span>'; 860 } 861 862 function htmlForDashboardLink(html, fileName) 863 { 864 var pathName = window.location.pathname; 865 var currentFileName = pathName.substring(pathName.lastIndexOf('/') + 1); 866 var isSelected = currentFileName == fileName; 867 var onClick = 'loadDashboard(\'' + fileName + '\')'; 868 return htmlForTopLink(html, onClick, isSelected); 869 } 870 871 function getRevisionLink(results, index, key, singleUrlTemplate, rangeUrlTemplate) 872 { 873 var currentRevision = parseInt(results[key][index], 10); 874 var previousRevision = parseInt(results[key][index + 1], 10); 875 876 function getSingleUrl() 877 { 878 return singleUrlTemplate.replace('<rev>', currentRevision); 879 } 880 881 function getRangeUrl() 882 { 883 return rangeUrlTemplate.replace('<rev1>', currentRevision).replace('<rev2>', previousRevision + 1); 884 } 885 886 if (currentRevision == previousRevision) 887 return 'At <a href="' + getSingleUrl() + '">r' + currentRevision + '</a>'; 888 else if (currentRevision - previousRevision == 1) 889 return '<a href="' + getSingleUrl() + '">r' + currentRevision + '</a>'; 890 else 891 return '<a href="' + getRangeUrl() + '">r' + (previousRevision + 1) + ' to r' + currentRevision + '</a>'; 892 } 893 894 function getChromiumRevisionLink(results, index) 895 { 896 return getRevisionLink( 897 results, 898 index, 899 CHROME_REVISIONS_KEY, 900 'http://src.chromium.org/viewvc/chrome?view=rev&revision=<rev>', 901 'http://build.chromium.org/f/chromium/perf/dashboard/ui/changelog.html?url=/trunk/src&range=<rev2>:<rev1>&mode=html'); 902 } 903 904 function getWebKitRevisionLink(results, index) 905 { 906 return getRevisionLink( 907 results, 908 index, 909 WEBKIT_REVISIONS_KEY, 910 'http://trac.webkit.org/changeset/<rev>', 911 'http://trac.webkit.org/log/trunk/?rev=<rev1>&stop_rev=<rev2>&limit=100&verbose=on'); 912 } 913 914 // "Decompresses" the RLE-encoding of test results so that we can query it 915 // by build index and test name. 916 // 917 // @param {Object} results results for the current builder 918 // @return Object with these properties: 919 // - testNames: array mapping test index to test names. 920 // - resultsByBuild: array of builds, for each build a (sparse) array of test 921 // results by test index. 922 // - flakyTests: array with the boolean value true at test indices that are 923 // considered flaky (more than one single-build failure). 924 // - flakyDeltasByBuild: array of builds, for each build a count of flaky 925 // test results by expectation, as well as a total. 926 function getTestResultsByBuild(builderResults) 927 { 928 var builderTestResults = builderResults[TESTS_KEY]; 929 var buildCount = builderResults[FIXABLE_COUNTS_KEY].length; 930 var testResultsByBuild = new Array(buildCount); 931 var flakyDeltasByBuild = new Array(buildCount); 932 933 // Pre-sizing the test result arrays for each build saves us ~250ms 934 var testCount = 0; 935 for (var testName in builderTestResults) 936 testCount++; 937 for (var i = 0; i < buildCount; i++) { 938 testResultsByBuild[i] = new Array(testCount); 939 testResultsByBuild[i][testCount - 1] = undefined; 940 flakyDeltasByBuild[i] = {}; 941 } 942 943 // Using indices instead of the full test names for each build saves us 944 // ~1500ms 945 var testIndex = 0; 946 var testNames = new Array(testCount); 947 var flakyTests = new Array(testCount); 948 949 // Decompress and "invert" test results (by build instead of by test) and 950 // determine which are flaky. 951 for (var testName in builderTestResults) { 952 var oneBuildFailureCount = 0; 953 954 testNames[testIndex] = testName; 955 var testResults = builderTestResults[testName].results; 956 for (var i = 0, rleResult, currentBuildIndex = 0; (rleResult = testResults[i]) && currentBuildIndex < buildCount; i++) { 957 var count = rleResult[RLE.LENGTH]; 958 var value = rleResult[RLE.VALUE]; 959 960 if (count == 1 && value in FAILURE_EXPECTATIONS_) 961 oneBuildFailureCount++; 962 963 for (var j = 0; j < count; j++) { 964 testResultsByBuild[currentBuildIndex++][testIndex] = value; 965 if (currentBuildIndex == buildCount) 966 break; 967 } 994 968 } 995 } 996 } 997 998 if (oneBuildFailureCount > 2) { 999 flakyTests[testIndex] = true; 1000 } 1001 1002 testIndex++; 1003 } 1004 1005 // Now that we know which tests are flaky, count the test results that are 1006 // from flaky tests for each build. 1007 testIndex = 0; 1008 for (var testName in builderTestResults) { 1009 if (!flakyTests[testIndex++]) { 1010 continue; 1011 } 1012 1013 var testResults = builderTestResults[testName].results; 1014 for (var i = 0, rleResult, currentBuildIndex = 0; 1015 (rleResult = testResults[i]) && currentBuildIndex < buildCount; 1016 i++) { 1017 var count = rleResult[RLE.LENGTH]; 1018 var value = rleResult[RLE.VALUE]; 1019 1020 for (var j = 0; j < count; j++) { 1021 var buildTestResults = flakyDeltasByBuild[currentBuildIndex++]; 1022 function addFlakyDelta(key) { 1023 if (!(key in buildTestResults)) { 1024 buildTestResults[key] = 0; 1025 } 1026 buildTestResults[key]++; 969 970 if (oneBuildFailureCount > 2) 971 flakyTests[testIndex] = true; 972 973 testIndex++; 974 } 975 976 // Now that we know which tests are flaky, count the test results that are 977 // from flaky tests for each build. 978 testIndex = 0; 979 for (var testName in builderTestResults) { 980 if (!flakyTests[testIndex++]) 981 continue; 982 983 var testResults = builderTestResults[testName].results; 984 for (var i = 0, rleResult, currentBuildIndex = 0; (rleResult = testResults[i]) && currentBuildIndex < buildCount; i++) { 985 var count = rleResult[RLE.LENGTH]; 986 var value = rleResult[RLE.VALUE]; 987 988 for (var j = 0; j < count; j++) { 989 var buildTestResults = flakyDeltasByBuild[currentBuildIndex++]; 990 function addFlakyDelta(key) 991 { 992 if (!(key in buildTestResults)) 993 buildTestResults[key] = 0; 994 buildTestResults[key]++; 995 } 996 addFlakyDelta(value); 997 if (value != 'P' && value != 'N') 998 addFlakyDelta('total'); 999 if (currentBuildIndex == buildCount) 1000 break; 1001 } 1027 1002 } 1028 addFlakyDelta(value); 1029 if (value != 'P' && value != 'N') { 1030 addFlakyDelta('total'); 1031 } 1032 if (currentBuildIndex == buildCount) { 1033 break; 1034 } 1035 } 1036 } 1037 } 1038 1039 return { 1040 testNames: testNames, 1041 resultsByBuild: testResultsByBuild, 1042 flakyTests: flakyTests, 1043 flakyDeltasByBuild: flakyDeltasByBuild 1044 }; 1003 } 1004 1005 return { 1006 testNames: testNames, 1007 resultsByBuild: testResultsByBuild, 1008 flakyTests: flakyTests, 1009 flakyDeltasByBuild: flakyDeltasByBuild 1010 }; 1045 1011 } 1046 1012 … … 1049 1015 1050 1016 document.addEventListener('mousedown', function(e) { 1051 // Clear the open popup, unless the click was inside the popup. 1052 var popup = $('popup'); 1053 if (popup && e.target != popup && 1054 !(popup.compareDocumentPosition(e.target) & 16)) { 1017 // Clear the open popup, unless the click was inside the popup. 1018 var popup = $('popup'); 1019 if (popup && e.target != popup && !(popup.compareDocumentPosition(e.target) & 16)) 1055 1020 hidePopup(); 1056 } 1057 }, false); 1021 }, false); 1058 1022 1059 1023 window.addEventListener('load', function() { 1060 1061 1062 logTime('Time to load JS',pageLoadStartTime);1063 1024 // This doesn't seem totally accurate as there is a race between 1025 // onload firing and the last script tag being executed. 1026 logTime('Time to load JS', g_pageLoadStartTime); 1027 }, false); -
trunk/Tools/TestResultServer/static-dashboards/flakiness_dashboard.html
r90964 r91021 346 346 function generatePage() 347 347 { 348 if ( currentState.useTestData)348 if (g_currentState.useTestData) 349 349 return; 350 350 … … 355 355 // tests expands to all tests that match the CSV list. 356 356 // result expands to all tests that ever have the given result 357 if ( currentState.tests ||currentState.result)357 if (g_currentState.tests || g_currentState.result) 358 358 generatePageForIndividualTests(individualTests()); 359 else if ( currentState.expectationsUpdate)359 else if (g_currentState.expectationsUpdate) 360 360 generatePageForExpectationsUpdate(); 361 361 else 362 generatePageForBuilder( currentState.builder);363 364 for (var builder in builders)362 generatePageForBuilder(g_currentState.builder); 363 364 for (var builder in g_builders) 365 365 processTestResultsForBuilderAsync(builder); 366 366 } … … 370 370 switch(key) { 371 371 case 'tests': 372 validateParameter( currentState, key, value,372 validateParameter(g_currentState, key, value, 373 373 function() { 374 374 return isValidName(value); … … 378 378 case 'result': 379 379 value = value.toUpperCase(); 380 validateParameter( currentState, key, value,380 validateParameter(g_currentState, key, value, 381 381 function() { 382 382 for (var result in LAYOUT_TEST_EXPECTATIONS_MAP_) { … … 389 389 390 390 case 'builder': 391 validateParameter( currentState, key, value,391 validateParameter(g_currentState, key, value, 392 392 function() { 393 return value in builders;393 return value in g_builders; 394 394 }); 395 395 return true; 396 396 397 397 case 'sortColumn': 398 validateParameter( currentState, key, value,398 validateParameter(g_currentState, key, value, 399 399 function() { 400 400 // Get all possible headers since the actual used set of headers 401 // depends on the values in currentState, which are currently being set.401 // depends on the values in g_currentState, which are currently being set. 402 402 var headers = tableHeaders(true); 403 403 for (var i = 0; i < headers.length; i++) { … … 410 410 411 411 case 'sortOrder': 412 validateParameter( currentState, key, value,412 validateParameter(g_currentState, key, value, 413 413 function() { 414 414 return value == FORWARD || value == BACKWARD; … … 419 419 case 'updateIndex': 420 420 case 'revision': 421 validateParameter( currentState, key, Number(value),421 validateParameter(g_currentState, key, Number(value), 422 422 function() { 423 423 return value.match(/^\d+$/); … … 436 436 case 'expectationsUpdate': 437 437 case 'showRunsOnBuilderPage': 438 currentState[key] = value == 'true';438 g_currentState[key] = value == 'true'; 439 439 return true; 440 440 … … 444 444 } 445 445 446 defaultStateValues = {446 g_defaultStateValues = { 447 447 sortOrder: BACKWARD, 448 448 sortColumn: 'flakiness', … … 459 459 showRunsOnBuilderPage: false, 460 460 updateIndex: 0, 461 builder: defaultBuilderName,461 builder: g_defaultBuilderName, 462 462 resultsHeight: 300, 463 463 revision: null … … 568 568 if (!g_allTests) { 569 569 g_allTests = {}; 570 for (var builder in builders)570 for (var builder in g_builders) 571 571 addTestsForBuilder(builder, g_allTests); 572 572 } … … 579 579 function individualTests() 580 580 { 581 if ( currentState.result)582 return allTestsWithResult( currentState.result);583 584 if (! currentState.tests)581 if (g_currentState.result) 582 return allTestsWithResult(g_currentState.result); 583 584 if (!g_currentState.tests) 585 585 return []; 586 586 … … 591 591 { 592 592 // Convert windows slashes to unix slashes. 593 var tests = currentState.tests.replace(/\\/g, '/');593 var tests = g_currentState.tests.replace(/\\/g, '/'); 594 594 var separator = stringContains(tests, ' ') ? ' ' : ','; 595 595 var testList = tests.split(separator); … … 678 678 function addTestsForBuilder(builder, testMapToPopulate) 679 679 { 680 var tests = resultsByBuilder[builder].tests;680 var tests = g_resultsByBuilder[builder].tests; 681 681 for (var test in tests) { 682 682 testMapToPopulate[test] = true; … … 698 698 if (!g_allTestsByPlatformAndBuildType[platform][buildType]) { 699 699 var tests = {}; 700 for (var thisBuilder in builders) {700 for (var thisBuilder in g_builders) { 701 701 var thisBuilderBuildInfo = platformAndBuildType(thisBuilder); 702 702 if (thisBuilderBuildInfo.buildType == buildType && thisBuilderBuildInfo.platform == platform) { … … 770 770 htmlArrays.bugs = []; 771 771 772 var tests = resultsByBuilder[resultsObject.builder].tests;772 var tests = g_resultsByBuilder[resultsObject.builder].tests; 773 773 774 774 var testObject = g_allExpectations[test]; … … 883 883 884 884 var expectationsArray = []; 885 for (var path in expectationsByTest)886 expectationsArray.push({path: path, expectations: expectationsByTest[path]});885 for (var path in g_expectationsByTest) 886 expectationsArray.push({path: path, expectations: g_expectationsByTest[path]}); 887 887 888 888 // Sort the array to hit more specific paths last. More specific … … 952 952 function processTestRunsForAllBuilders() 953 953 { 954 for (var builder in builders)954 for (var builder in g_builders) 955 955 processTestRunsForBuilder(builder); 956 956 } … … 961 961 return; 962 962 963 if (! resultsByBuilder[builderName]) {963 if (!g_resultsByBuilder[builderName]) { 964 964 console.error('No tests found for ' + builderName); 965 965 g_perBuilderFailures[builderName] = []; … … 976 976 977 977 var failures = []; 978 var allTestsForThisBuilder = resultsByBuilder[builderName].tests;978 var allTestsForThisBuilder = g_resultsByBuilder[builderName].tests; 979 979 980 980 for (var test in allTestsForThisBuilder) { … … 982 982 populateExpectationsData(resultsForTest); 983 983 984 var rawTest = resultsByBuilder[builderName].tests[test];984 var rawTest = g_resultsByBuilder[builderName].tests[test]; 985 985 resultsForTest.rawTimes = rawTest.times; 986 986 var rawResults = rawTest.results; … … 1093 1093 // test_expectations.txt, delete all the legacyExpectationsSemantics 1094 1094 // code. 1095 if ( currentState.legacyExpectationsSemantics) {1095 if (g_currentState.legacyExpectationsSemantics) { 1096 1096 if (element == 'FAIL') { 1097 1097 for (var i = 0; i < FAIL_RESULTS.length; i++) { … … 1114 1114 // test_expectations.txt, delete all the legacyExpectationsSemantics 1115 1115 // code. 1116 if ( currentState.legacyExpectationsSemantics) {1116 if (g_currentState.legacyExpectationsSemantics) { 1117 1117 if (expectation == 'FAIL') { 1118 1118 for (var j = 0; j < FAIL_RESULTS.length; j++) { … … 1219 1219 { 1220 1220 var currentIndex = 0; 1221 var rawResults = resultsByBuilder[builder].tests[testName].results;1221 var rawResults = g_resultsByBuilder[builder].tests[testName].results; 1222 1222 for (var i = 0; i < rawResults.length; i++) { 1223 1223 currentIndex += rawResults[i][RLE.LENGTH]; … … 1231 1231 function buildNumbersForFailures(builder, testName) 1232 1232 { 1233 var rawResults = resultsByBuilder[builder].tests[testName].results;1234 var buildNumbers = resultsByBuilder[builder].buildNumbers;1233 var rawResults = g_resultsByBuilder[builder].tests[testName].results; 1234 var buildNumbers = g_resultsByBuilder[builder].buildNumbers; 1235 1235 var index = 0; 1236 1236 var failures = []; … … 1249 1249 function pathToFailureLog(testName) 1250 1250 { 1251 return '/steps/' + currentState.testType + '/logs/' + testName.split('.')[1]1251 return '/steps/' + g_currentState.testType + '/logs/' + testName.split('.')[1] 1252 1252 } 1253 1253 … … 1256 1256 var html = ''; 1257 1257 1258 var time = resultsByBuilder[builder].secondsSinceEpoch[index];1258 var time = g_resultsByBuilder[builder].secondsSinceEpoch[index]; 1259 1259 if (time) { 1260 1260 var date = new Date(time * 1000); … … 1262 1262 } 1263 1263 1264 var buildNumber = resultsByBuilder[builder].buildNumbers[index];1264 var buildNumber = g_resultsByBuilder[builder].buildNumbers[index]; 1265 1265 var builderMaster = getBuilderMaster(builder); 1266 1266 var buildBasePath = builderMaster.getLogPath(builder, buildNumber); … … 1268 1268 html += '<ul><li>' + linkHTMLToOpenWindow(buildBasePath, 'Build log') + 1269 1269 '</li><li>' + 1270 createBlameListHTML( resultsByBuilder[builder].webkitRevision, index,1270 createBlameListHTML(g_resultsByBuilder[builder].webkitRevision, index, 1271 1271 'http://trac.webkit.org/log/?verbose=on&rev=', '&stop_rev=', 1272 1272 'WebKit') + … … 1274 1274 1275 1275 if (builderMaster == WEBKIT_BUILDER_MASTER) { 1276 var revision = resultsByBuilder[builder].webkitRevision[index];1276 var revision = g_resultsByBuilder[builder].webkitRevision[index]; 1277 1277 html += '<li><span class=link onclick="setQueryParameter(\'revision\',' + 1278 1278 revision + ')">Show results for WebKit r' + revision + … … 1280 1280 } else { 1281 1281 html += '<li>' + 1282 createBlameListHTML( resultsByBuilder[builder].chromeRevision, index,1282 createBlameListHTML(g_resultsByBuilder[builder].chromeRevision, index, 1283 1283 'http://build.chromium.org/f/chromium/perf/dashboard/ui/changelog.html?url=/trunk/src&mode=html&range=', ':', 'Chrome') + 1284 1284 '</li>'; 1285 1285 1286 var chromeRevision = resultsByBuilder[builder].chromeRevision[index];1286 var chromeRevision = g_resultsByBuilder[builder].chromeRevision[index]; 1287 1287 if (chromeRevision && isLayoutTestResults()) { 1288 html += '<li><a href="' + TEST_RESULTS_BASE_PATH + builders[builder] +1288 html += '<li><a href="' + TEST_RESULTS_BASE_PATH + g_builders[builder] + 1289 1289 '/' + chromeRevision + '/layout-test-results.zip">layout-test-results.zip</a></li>'; 1290 1290 } … … 1306 1306 function htmlForTestResults(test) 1307 1307 { 1308 if (! currentState.showRunsOnBuilderPage && !isCrossBuilderView())1308 if (!g_currentState.showRunsOnBuilderPage && !isCrossBuilderView()) 1309 1309 return '<td>' + test.flips; 1310 1310 … … 1314 1314 var builder = test.builder; 1315 1315 var builderMaster = getBuilderMaster(builder); 1316 var buildNumbers = resultsByBuilder[builder].buildNumbers;1316 var buildNumbers = g_resultsByBuilder[builder].buildNumbers; 1317 1317 1318 1318 var indexToReplaceCurrentResult = -1; … … 1348 1348 1349 1349 var extraClassNames = ''; 1350 var webkitRevision = resultsByBuilder[builder].webkitRevision;1350 var webkitRevision = g_resultsByBuilder[builder].webkitRevision; 1351 1351 var isWebkitMerge = webkitRevision[i + 1] && webkitRevision[i] != webkitRevision[i + 1]; 1352 1352 if (isWebkitMerge && builderMaster != WEBKIT_BUILDER_MASTER) … … 1373 1373 1374 1374 if (tests.length) { 1375 html += '<h3>Have not failed in last ' + resultsByBuilder[builder].buildNumbers.length + ' runs.</h3><div id="passing-tests">';1375 html += '<h3>Have not failed in last ' + g_resultsByBuilder[builder].buildNumbers.length + ' runs.</h3><div id="passing-tests">'; 1376 1376 1377 1377 for (var i = 0; i < tests.length; i++) … … 1384 1384 html += '<h3>' + linkHTMLToToggleState('showSkipped', 'Skipped tests in test_expectations.txt') + '</h3>'; 1385 1385 1386 if ( currentState.showSkipped)1386 if (g_currentState.showSkipped) 1387 1387 html += '<div id="passing-tests">' + open + skippedPaths.join('</div>' + open) + '</div></div>'; 1388 1388 } … … 1394 1394 { 1395 1395 if (testResult.isWontFixSkip) 1396 return ! currentState.showWontFixSkip;1396 return !g_currentState.showWontFixSkip; 1397 1397 1398 1398 if (testResult.isFlaky) 1399 return ! currentState.showFlaky;1399 return !g_currentState.showFlaky; 1400 1400 1401 1401 if (isSlowTest(testResult)) 1402 return ! currentState.showSlow;1402 return !g_currentState.showSlow; 1403 1403 1404 1404 if (testResult.meetsExpectations) 1405 return ! currentState.showCorrectExpectations;1406 1407 return ! currentState.showWrongExpectations;1405 return !g_currentState.showCorrectExpectations; 1406 1407 return !g_currentState.showWrongExpectations; 1408 1408 } 1409 1409 … … 1429 1429 function isCrossBuilderView() 1430 1430 { 1431 return currentState.tests || currentState.result ||currentState.expectationsUpdate;1431 return g_currentState.tests || g_currentState.result || g_currentState.expectationsUpdate; 1432 1432 } 1433 1433 … … 1443 1443 if (isLayoutTestResults() || opt_getAll) { 1444 1444 headers.push('bugs'); 1445 if (isCrossBuilderView() || currentState.showRunsOnBuilderPage || opt_getAll)1445 if (isCrossBuilderView() || g_currentState.showRunsOnBuilderPage || opt_getAll) 1446 1446 headers.push('modifiers', 'expectations'); 1447 1447 } 1448 1448 1449 if ( currentState.showRunsOnBuilderPage || opt_getAll || isCrossBuilderView())1449 if (g_currentState.showRunsOnBuilderPage || opt_getAll || isCrossBuilderView()) 1450 1450 headers.push('missing', 'extra'); 1451 1451 … … 1455 1455 var FLIPS_HEADER = 'flakiness (number of flips)'; 1456 1456 1457 if ( currentState.showRunsOnBuilderPage || opt_getAll)1457 if (g_currentState.showRunsOnBuilderPage || opt_getAll) 1458 1458 headers.push(FLAKINESS_HEADER); 1459 1459 1460 if (! currentState.showRunsOnBuilderPage || opt_getAll)1460 if (!g_currentState.showRunsOnBuilderPage || opt_getAll) 1461 1461 headers.push(FLIPS_HEADER); 1462 1462 … … 1515 1515 // Use the first word of the header title as the sortkey 1516 1516 var thisSortValue = sortColumnFromTableHeader(headerName); 1517 var arrowHTML = thisSortValue == currentState.sortColumn ?1518 '<span class=' + currentState.sortOrder + '>' + (currentState.sortOrder == FORWARD ? '↑' : '↓' ) + '</span>' : '';1517 var arrowHTML = thisSortValue == g_currentState.sortColumn ? 1518 '<span class=' + g_currentState.sortOrder + '>' + (g_currentState.sortOrder == FORWARD ? '↑' : '↓' ) + '</span>' : ''; 1519 1519 return '<th sortValue=' + thisSortValue + 1520 1520 // Extend last th through all the rest of the columns. … … 1606 1606 var sort = 'sortColumn'; 1607 1607 var orderKey = 'sortOrder'; 1608 if (sortValue == currentState[sort] &¤tState[orderKey] == FORWARD)1608 if (sortValue == g_currentState[sort] && g_currentState[orderKey] == FORWARD) 1609 1609 order = BACKWARD; 1610 1610 else … … 1681 1681 { 1682 1682 // Always show all runs when auto-updating expectations. 1683 if (! currentState.showAllRuns)1683 if (!g_currentState.showAllRuns) 1684 1684 setQueryParameter('showAllRuns', true); 1685 1685 … … 1702 1702 } 1703 1703 1704 for (var builder in builders) {1704 for (var builder in g_builders) { 1705 1705 var tests = g_perBuilderWithExpectationsButNoFailures[builder] 1706 1706 for (var i = 0; i < tests.length; i++) { … … 1727 1727 function showUpdateInfoForTest(testsNeedingUpdate, keys) 1728 1728 { 1729 var test = keys[ currentState.updateIndex];1729 var test = keys[g_currentState.updateIndex]; 1730 1730 document.body.innerHTML = '<b>' + test + '</b>' + 1731 '<div style="float:right">' + ( currentState.updateIndex + 1) + ' of ' +1731 '<div style="float:right">' + (g_currentState.updateIndex + 1) + ' of ' + 1732 1732 + keys.length + ' tests</div><br><br>'; 1733 1733 … … 1744 1744 previousBtn.addEventListener('click', 1745 1745 function() { 1746 setUpdateIndex( currentState.updateIndex - 1, testsNeedingUpdate, keys);1746 setUpdateIndex(g_currentState.updateIndex - 1, testsNeedingUpdate, keys); 1747 1747 }, 1748 1748 false); … … 1806 1806 function handleUpdate(testsNeedingUpdate, keys) 1807 1807 { 1808 var test = keys[ currentState.updateIndex];1808 var test = keys[g_currentState.updateIndex]; 1809 1809 var updates = testsNeedingUpdate[test]; 1810 1810 for (var builder in updates) { … … 1830 1830 function nextUpdate(testsNeedingUpdate, keys) 1831 1831 { 1832 setUpdateIndex( currentState.updateIndex + 1, testsNeedingUpdate, keys);1832 setUpdateIndex(g_currentState.updateIndex + 1, testsNeedingUpdate, keys); 1833 1833 } 1834 1834 … … 1871 1871 html = htmlForTestTable(html); 1872 1872 } else { 1873 if ( expectationsByTest[test]) {1874 for (var i = 0; i < expectationsByTest[test].length; i++) {1875 html += '<div>' + expectationsByTest[test][i].modifiers + ' | ' +1876 expectationsByTest[test][i].expectations + '</div>';1873 if (g_expectationsByTest[test]) { 1874 for (var i = 0; i < g_expectationsByTest[test].length; i++) { 1875 html += '<div>' + g_expectationsByTest[test][i].modifiers + ' | ' + 1876 g_expectationsByTest[test][i].expectations + '</div>'; 1877 1877 } 1878 1878 } … … 1887 1887 html += ' | ' + linkHTMLToToggleState('showLargeExpectations', 'large thumbnails'); 1888 1888 if (builderMaster == WEBKIT_BUILDER_MASTER) { 1889 var revision = currentState.revision || '';1889 var revision = g_currentState.revision || ''; 1890 1890 html += '<form onsubmit="setQueryParameter(\'revision\', revision.value);' + 1891 1891 'return false;">Show results for WebKit revision: ' + … … 1897 1897 html += ' | <span>Results height:<input ' + 1898 1898 'onchange="setQueryParameter(\'resultsHeight\',this.value)" value="' + 1899 currentState.resultsHeight + '" style="width:2.5em">px</span>';1899 g_currentState.resultsHeight + '" style="width:2.5em">px</span>'; 1900 1900 } 1901 1901 html += '</div></div>'; … … 1985 1985 childContainer.className = 'expectations-item'; 1986 1986 item.className = 'expectation ' + fileExtension; 1987 if ( currentState.showLargeExpectations)1987 if (g_currentState.showLargeExpectations) 1988 1988 item.className += ' large'; 1989 1989 childContainer.appendChild(item); … … 2199 2199 item.src = dummyNode.src; 2200 2200 item.className = 'non-webkit-results'; 2201 item.style.height = currentState.resultsHeight + 'px';2201 item.style.height = g_currentState.resultsHeight + 'px'; 2202 2202 container.appendChild(item); 2203 2203 } … … 2211 2211 function buildInfoForRevision(builder, revision) 2212 2212 { 2213 var revisions = resultsByBuilder[builder].webkitRevision;2213 var revisions = g_resultsByBuilder[builder].webkitRevision; 2214 2214 var revisionStart = 0, revisionEnd = 0, buildNumber = 0; 2215 2215 for (var i = 0; i < revisions.length; i++) { … … 2217 2217 revisionStart = revisions[i - 1]; 2218 2218 revisionEnd = revisions[i]; 2219 buildNumber = resultsByBuilder[builder].buildNumbers[i - 1];2219 buildNumber = g_resultsByBuilder[builder].buildNumbers[i - 1]; 2220 2220 break; 2221 2221 } … … 2239 2239 revisionContainer.textContent = "Showing results for: " 2240 2240 expectationsContainer.appendChild(revisionContainer); 2241 for (var builder in builders) {2241 for (var builder in g_builders) { 2242 2242 if (getBuilderMaster(builder) == WEBKIT_BUILDER_MASTER) { 2243 var latestRevision = currentState.revision ||resultsByBuilder[builder].webkitRevision[0];2243 var latestRevision = g_currentState.revision || g_resultsByBuilder[builder].webkitRevision[0]; 2244 2244 var buildInfo = buildInfoForRevision(builder, latestRevision); 2245 2245 var revisionInfo = document.createElement('div'); … … 2271 2271 var actualResultSuffixes = ['-actual.txt', '-actual.png', '-crash-log.txt', '-diff.txt', '-wdiff.html', '-diff.png']; 2272 2272 2273 for (var builder in builders) {2273 for (var builder in g_builders) { 2274 2274 var actualResultsBase; 2275 2275 if (getBuilderMaster(builder) == WEBKIT_BUILDER_MASTER) { 2276 var latestRevision = currentState.revision ||resultsByBuilder[builder].webkitRevision[0];2276 var latestRevision = g_currentState.revision || g_resultsByBuilder[builder].webkitRevision[0]; 2277 2277 var buildInfo = buildInfoForRevision(builder, latestRevision); 2278 2278 actualResultsBase = 'http://build.webkit.org/results/' + builder + 2279 2279 '/r' + buildInfo.revisionStart + ' (' + buildInfo.buildNumber + ')/'; 2280 2280 } else 2281 actualResultsBase = TEST_RESULTS_BASE_PATH + builders[builder] + '/results/layout-test-results/';2281 actualResultsBase = TEST_RESULTS_BASE_PATH + g_builders[builder] + '/results/layout-test-results/'; 2282 2282 2283 2283 for (var i = 0; i < actualResultSuffixes.length; i++) { … … 2323 2323 function appendExpectations() 2324 2324 { 2325 var expectations = currentState.showExpectations ? document.getElementsByClassName('expectations') : [];2325 var expectations = g_currentState.showExpectations ? document.getElementsByClassName('expectations') : []; 2326 2326 // Loading expectations is *very* slow. Use a large timeout to avoid 2327 2327 // totally hanging the renderer. … … 2346 2346 appendHTML(htmlForIndividualTests(chunk)); 2347 2347 }, appendExpectations, 500); 2348 $('tests-input').value = currentState.tests;2348 $('tests-input').value = g_currentState.tests; 2349 2349 } 2350 2350 … … 2374 2374 var extraHTML = ''; 2375 2375 if (!isCrossBuilderView()) 2376 extraHTML += checkboxHTML('showRunsOnBuilderPage', 'Show flakiness details', currentState.showRunsOnBuilderPage);2376 extraHTML += checkboxHTML('showRunsOnBuilderPage', 'Show flakiness details', g_currentState.showRunsOnBuilderPage); 2377 2377 2378 2378 var html = getHTMLForTestTypeSwitcher(false, extraHTML, isCrossBuilderView()); … … 2394 2394 function linkHTMLToToggleState(key, linkText) 2395 2395 { 2396 var isTrue = currentState[key];2396 var isTrue = g_currentState[key]; 2397 2397 return '<span class=link onclick="setQueryParameter(\'' + key + '\', ' + 2398 2398 !isTrue + ')">' + (isTrue ? 'Hide' : 'Show') + ' ' + linkText + '</span>'; … … 2404 2404 2405 2405 var results = g_perBuilderFailures[builderName]; 2406 sortTests(results, currentState.sortColumn,currentState.sortOrder);2406 sortTests(results, g_currentState.sortColumn, g_currentState.sortOrder); 2407 2407 2408 2408 var testsHTML = ''; … … 2456 2456 function isInvalidKeyForCrossBuilderView(key) 2457 2457 { 2458 return !(key in VALID_KEYS_FOR_CROSS_BUILDER_VIEW) && !(key in defaultCrossDashboardStateValues);2458 return !(key in VALID_KEYS_FOR_CROSS_BUILDER_VIEW) && !(key in g_defaultCrossDashboardStateValues); 2459 2459 } 2460 2460 … … 2462 2462 { 2463 2463 if (isCrossBuilderView()) 2464 delete defaultStateValues.builder;2464 delete g_defaultStateValues.builder; 2465 2465 else 2466 defaultStateValues.builder =defaultBuilderName;2466 g_defaultStateValues.builder = g_defaultBuilderName; 2467 2467 } 2468 2468 … … 2474 2474 if (key == 'tests') { 2475 2475 // Entering cross-builder view, only keep valid keys for that view. 2476 for (var currentKey in currentState) {2476 for (var currentKey in g_currentState) { 2477 2477 if (isInvalidKeyForCrossBuilderView(currentKey)) { 2478 delete currentState[currentKey];2478 delete g_currentState[currentKey]; 2479 2479 } 2480 2480 } 2481 2481 } else if (isInvalidKeyForCrossBuilderView(key)) { 2482 delete currentState.tests;2483 delete currentState.result;2482 delete g_currentState.tests; 2483 delete g_currentState.result; 2484 2484 } 2485 2485 } -
trunk/Tools/TestResultServer/static-dashboards/flakiness_dashboard_tests.js
r90674 r91021 49 49 allExpectations = null; 50 50 allTests = null; 51 expectationsByTest = {};52 resultsByBuilder = {};53 builders = {};51 g_expectationsByTest = {}; 52 g_resultsByBuilder = {}; 53 g_builders = {}; 54 54 } 55 55 … … 66 66 */ 67 67 function runExpectationsTest(builder, test, expectations, modifiers) { 68 builders[builder] = true;68 g_builders[builder] = true; 69 69 70 70 // Put in some dummy results. processExpectations expects the test to be … … 72 72 var tests = {}; 73 73 tests[test] = {'results': [[100, 'F']], 'times': [[100, 0]]}; 74 resultsByBuilder[builder] = {'tests': tests};74 g_resultsByBuilder[builder] = {'tests': tests}; 75 75 76 76 processExpectations(); … … 98 98 {'modifiers': 'RELEASE', 'expectations': 'FAIL'} 99 99 ]; 100 expectationsByTest[test] = expectationsArray;100 g_expectationsByTest[test] = expectationsArray; 101 101 runExpectationsTest(builder, test, 'FAIL', 'RELEASE'); 102 102 } … … 109 109 {'modifiers': 'DEBUG', 'expectations': 'CRASH'} 110 110 ]; 111 expectationsByTest[test] = expectationsArray;111 g_expectationsByTest[test] = expectationsArray; 112 112 runExpectationsTest(builder, test, 'FAIL', 'RELEASE'); 113 113 } … … 120 120 {'modifiers': 'DEBUG', 'expectations': 'CRASH'} 121 121 ]; 122 expectationsByTest[test] = expectationsArray;122 g_expectationsByTest[test] = expectationsArray; 123 123 runExpectationsTest(builder, test, 'CRASH', 'DEBUG'); 124 124 } … … 126 126 function testOverrideJustBuildType() { 127 127 var test = 'bar/1.html'; 128 expectationsByTest['bar'] = [128 g_expectationsByTest['bar'] = [ 129 129 {'modifiers': 'WONTFIX', 'expectations': 'FAIL PASS TIMEOUT'} 130 130 ]; 131 expectationsByTest[test] = [131 g_expectationsByTest[test] = [ 132 132 {'modifiers': 'WONTFIX MAC', 'expectations': 'FAIL'}, 133 133 {'modifiers': 'LINUX DEBUG', 'expectations': 'CRASH'}, -
trunk/Tools/TestResultServer/static-dashboards/timeline_explorer.html
r90674 r91021 113 113 function generatePage() { 114 114 buildIndicesByTimestamp = {}; 115 var results = resultsByBuilder[currentState.builder];115 var results = g_resultsByBuilder[g_currentState.builder]; 116 116 117 117 for (var i = 0; i < results[FIXABLE_COUNTS_KEY].length; i++) { … … 120 120 } 121 121 122 if ( currentState.buildTimestamp != -1 &&123 currentState.buildTimestamp in buildIndicesByTimestamp) {122 if (g_currentState.buildTimestamp != -1 && 123 g_currentState.buildTimestamp in buildIndicesByTimestamp) { 124 124 var newBuildIndex = 125 buildIndicesByTimestamp[ currentState.buildTimestamp];125 buildIndicesByTimestamp[g_currentState.buildTimestamp]; 126 126 127 127 if (newBuildIndex == currentBuildIndex) { … … 141 141 false, 142 142 checkboxHTML('ignoreFlakyTests', 'Ignore flaky tests', 143 currentState.ignoreFlakyTests, 'currentBuildIndex = -1')143 g_currentState.ignoreFlakyTests, 'currentBuildIndex = -1') 144 144 ); 145 145 … … 150 150 var startTime = Date.now(); 151 151 currentBuilderTestResults = 152 getTestResultsByBuild( resultsByBuilder[currentState.builder]);152 getTestResultsByBuild(g_resultsByBuilder[g_currentState.builder]); 153 153 console.log( 154 154 'Time to get test results by build: ' + (Date.now() - startTime)); … … 158 158 switch(key) { 159 159 case 'buildTimestamp': 160 currentState.buildTimestamp = parseInt(value, 10);160 g_currentState.buildTimestamp = parseInt(value, 10); 161 161 return true; 162 162 case 'ignoreFlakyTests': 163 currentState.ignoreFlakyTests = value == 'true';163 g_currentState.ignoreFlakyTests = value == 'true'; 164 164 return true; 165 165 default: … … 168 168 } 169 169 170 defaultStateValues = {170 g_defaultStateValues = { 171 171 buildTimestamp: -1, 172 builder: defaultBuilderName,172 builder: g_defaultBuilderName, 173 173 ignoreFlakyTests: true 174 174 }; 175 175 176 176 function updateTimelineForBuilder() { 177 var builder = currentState.builder;178 var results = resultsByBuilder[builder];177 var builder = g_currentState.builder; 178 var results = g_resultsByBuilder[builder]; 179 179 var graphData = []; 180 180 … … 188 188 var failureCount = Math.min(results[FIXABLE_COUNT_KEY][i], 10000); 189 189 190 if ( currentState.ignoreFlakyTests) {190 if (g_currentState.ignoreFlakyTests) { 191 191 failureCount -= 192 192 currentBuilderTestResults.flakyDeltasByBuild[i].total || 0; … … 300 300 var resultsUrl = 301 301 'http://build.chromium.org/f/chromium/layout_test_results/' + 302 builders[builder] + '/' + results[CHROME_REVISIONS_KEY][index];302 g_builders[builder] + '/' + results[CHROME_REVISIONS_KEY][index]; 303 303 } 304 304 … … 337 337 var previousCount = 338 338 results[FIXABLE_COUNTS_KEY][index + 1][expectationKey]; 339 if ( currentState.ignoreFlakyTests) {339 if (g_currentState.ignoreFlakyTests) { 340 340 currentCount -= flakyDeltasByBuild[index][expectationKey] || 0; 341 341 previousCount -= flakyDeltasByBuild[index + 1][expectationKey] || 0; … … 348 348 var currentTotal = results[FIXABLE_COUNT_KEY][index]; 349 349 var previousTotal = results[FIXABLE_COUNT_KEY][index + 1]; 350 if ( currentState.ignoreFlakyTests) {350 if (g_currentState.ignoreFlakyTests) { 351 351 currentTotal -= flakyDeltasByBuild[index].total || 0; 352 352 previousTotal -= flakyDeltasByBuild[index + 1].total || 0; … … 388 388 var deltas = {}; 389 389 function addDelta(category, testIndex) { 390 if ( currentState.ignoreFlakyTests && flakyTests[testIndex]) {390 if (g_currentState.ignoreFlakyTests && flakyTests[testIndex]) { 391 391 return; 392 392 } … … 464 464 case 'Left': 465 465 selectBuild( 466 resultsByBuilder[currentState.builder],467 currentState.builder,466 g_resultsByBuilder[g_currentState.builder], 467 g_currentState.builder, 468 468 dygraph, 469 469 currentBuildIndex + 1); … … 471 471 case 'Right': 472 472 selectBuild( 473 resultsByBuilder[currentState.builder],474 currentState.builder,473 g_resultsByBuilder[g_currentState.builder], 474 g_currentState.builder, 475 475 dygraph, 476 476 currentBuildIndex - 1); -
trunk/Tools/TestResultServer/static-dashboards/treemap.html
r90674 r91021 155 155 } 156 156 157 var resultsByBuilder = {};157 var g_resultsByBuilder = {}; 158 158 159 159 function ADD_RESULTS(data) { 160 160 // TODO(ojan): We should probably include the builderName in the JSON 161 161 // rather than relying on only loading one JSON file per page. 162 if (! resultsByBuilder[currentState.builder])163 resultsByBuilder[currentState.builder] = data;162 if (!g_resultsByBuilder[g_currentState.builder]) 163 g_resultsByBuilder[g_currentState.builder] = data; 164 164 165 165 handleLocationChange(); … … 169 169 170 170 function generatePage() { 171 if (! resultsByBuilder[currentState.builder]) {172 handleResourceLoadError( currentState.builder);171 if (!g_resultsByBuilder[g_currentState.builder]) { 172 handleResourceLoadError(g_currentState.builder); 173 173 return; 174 174 } … … 176 176 isGeneratingPage = true; 177 177 178 var rawTree = resultsByBuilder[currentState.builder];178 var rawTree = g_resultsByBuilder[g_currentState.builder]; 179 179 var webtree = convertToWebTreemapFormat('LayoutTests', rawTree); 180 180 appendTreemap($('map'), webtree); 181 181 182 if ( currentState.treemapfocus)183 focusPath(webtree, currentState.treemapfocus)182 if (g_currentState.treemapfocus) 183 focusPath(webtree, g_currentState.treemapfocus) 184 184 185 185 isGeneratingPage = false; … … 214 214 switch(key) { 215 215 case 'builder': 216 validateParameter( currentState, key, value,216 validateParameter(g_currentState, key, value, 217 217 function() { 218 return value in builders;218 return value in g_builders; 219 219 }); 220 220 … … 222 222 223 223 case 'treemapfocus': 224 validateParameter( currentState, key, value,224 validateParameter(g_currentState, key, value, 225 225 function() { 226 226 // TODO(ojan): There's probably a simpler regexp here. Just trying to match ascii + forward-slash. … … 236 236 } 237 237 238 defaultStateValues = {239 builder: defaultBuilderName238 g_defaultStateValues = { 239 builder: g_defaultBuilderName 240 240 }; 241 241 242 242 function handleQueryParameterChange(params) { 243 if (! resultsByBuilder[currentState.builder])244 appendJSONScriptElementFor( currentState.builder);243 if (!g_resultsByBuilder[g_currentState.builder]) 244 appendJSONScriptElementFor(g_currentState.builder); 245 245 246 246 for (var param in params) { … … 257 257 $('map').innerHTML = '<span class=error>Could not load data for ' + builderName + '. ' + 258 258 'Either there was a server-side error or ' + builderName + ' does not run ' + 259 currentState.testType + '.</span>';259 g_currentState.testType + '.</span>'; 260 260 } 261 261 … … 306 306 307 307 parseParameters(); 308 appendJSONScriptElementFor( currentState.builder);308 appendJSONScriptElementFor(g_currentState.builder); 309 309 </script>
Note: See TracChangeset
for help on using the changeset viewer.