1// Copyright (C) 2012 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 29function LOAD_BUILDBOT_DATA(builderData) 30{ 31 builders.masters = {}; 32 var groups = {}; 33 var testTypes = {}; 34 var testTypesThatDoNotUpload = {}; 35 builders.noUploadTestTypes = builderData['no_upload_test_types'] 36 builderData['masters'].forEach(function(master) { 37 builders.masters[master.name] = new builders.BuilderMaster(master); 38 39 master.groups.forEach(function(group) { groups[group] = true; }); 40 41 Object.keys(master.tests).forEach(function(testType) { 42 if (builders.testTypeUploadsToFlakinessDashboardServer(testType)) 43 testTypes[testType] = true; 44 else 45 testTypesThatDoNotUpload[testType] = true; 46 }); 47 }); 48 builders.groups = Object.keys(groups); 49 builders.groups.sort(); 50 builders.testTypes = Object.keys(testTypes); 51 builders.testTypes.sort(); 52 // FIXME: Expose this in the flakiness dashboard UI and give a clear error message 53 // pointing to a bug about getting the test type in question uploading results. 54 builders.testTypesThatDoNotUpload = Object.keys(testTypesThatDoNotUpload); 55 builders.testTypesThatDoNotUpload.sort(); 56} 57 58var builders = builders || {}; 59 60(function() { 61 62builders.testTypeUploadsToFlakinessDashboardServer = function(testType) 63{ 64 for (var i = 0; i < builders.noUploadTestTypes.length; i++) { 65 if (string.contains(testType, builders.noUploadTestTypes[i])) 66 return false; 67 } 68 return true; 69} 70 71var currentBuilderGroup = {}; 72var testTypesThatRunToTBlinkBots = ['layout-tests', 'webkit_unit_tests']; 73 74builders.getBuilderGroup = function(groupName, testType) 75{ 76 if (!builders in currentBuilderGroup) { 77 currentBuilderGroup = builders.loadBuildersList(groupName, testType); 78 } 79 return currentBuilderGroup; 80} 81 82function isChromiumWebkitTipOfTreeTestRunner(builder) 83{ 84 return !isChromiumWebkitDepsTestRunner(builder); 85} 86 87function isChromiumWebkitDepsTestRunner(builder) 88{ 89 return builder.indexOf('(deps)') != -1; 90} 91 92builders._builderFilter = function(groupName, masterName, testType) 93{ 94 if (testTypesThatRunToTBlinkBots.indexOf(testType) == -1) { 95 if (masterName == 'ChromiumWebkit' && groupName != '@ToT Blink') 96 return function() { return false }; 97 return null; 98 } 99 100 if (groupName == '@ToT Blink') 101 return isChromiumWebkitTipOfTreeTestRunner; 102 103 if (groupName == '@ToT Chromium') 104 return isChromiumWebkitDepsTestRunner; 105 106 return null; 107} 108 109// FIXME: When we change to show multiple groups at once, this will need to 110// change to key off groupName and builderName. 111builders.master = function(builderName) 112{ 113 return builders.builderToMaster[builderName]; 114} 115 116builders.loadBuildersList = function(groupName, testType) 117{ 118 if (!groupName || !testType) { 119 console.warn("Group name and/or test type were empty."); 120 return new builders.BuilderGroup(false); 121 } 122 var builderGroup = new builders.BuilderGroup(groupName == '@ToT Blink'); 123 builders.builderToMaster = {}; 124 125 for (masterName in builders.masters) { 126 if (!builders.masters[masterName]) 127 continue; 128 129 var master = builders.masters[masterName]; 130 var hasTest = testType in master.tests; 131 var isInGroup = master.groups.indexOf(groupName) != -1; 132 133 if (hasTest && isInGroup) { 134 var builderList = master.tests[testType].builders; 135 var builderFilter = builders._builderFilter(groupName, masterName, testType); 136 if (builderFilter) 137 builderList = builderList.filter(builderFilter); 138 builderGroup.append(builderList); 139 140 builderList.forEach(function (builderName) { 141 builders.builderToMaster[builderName] = master; 142 }); 143 } 144 } 145 146 currentBuilderGroup = builderGroup; 147 return currentBuilderGroup; 148} 149 150builders.getAllGroupNames = function() 151{ 152 return builders.groups; 153} 154 155builders.BuilderMaster = function(master_data) 156{ 157 this.name = master_data.name; 158 this.basePath = 'http://build.chromium.org/p/' + master_data.url_name; 159 this.tests = master_data.tests; 160 this.groups = master_data.groups; 161} 162 163builders.BuilderMaster.prototype = { 164 logPath: function(builder, buildNumber) 165 { 166 return this.builderPath(builder) + '/builds/' + buildNumber; 167 }, 168 builderPath: function(builder) 169 { 170 return this.basePath + '/builders/' + builder; 171 }, 172 builderJsonPath: function() 173 { 174 return this.basePath + '/json/builders'; 175 }, 176} 177 178builders.BuilderGroup = function(isToTBlink) 179{ 180 this.isToTBlink = isToTBlink; 181 // Map of builderName (the name shown in the waterfall) to builderPath (the 182 // path used in the builder's URL) 183 this.builders = {}; 184} 185 186builders.BuilderGroup.prototype = { 187 append: function(builders) { 188 builders.forEach(function(builderName) { 189 this.builders[builderName] = builderName.replace(/[ .()]/g, '_'); 190 }, this); 191 }, 192 defaultBuilder: function() 193 { 194 for (var builder in this.builders) 195 return builder; 196 console.error('There are no builders in this builder group.'); 197 }, 198 master: function() 199 { 200 return builders.master(this.defaultBuilder()); 201 }, 202} 203 204builders.groupNamesForTestType = function(testType) 205{ 206 var groupNames = []; 207 for (masterName in builders.masters) { 208 var master = builders.masters[masterName]; 209 if (testType in master.tests) { 210 groupNames = groupNames.concat(master.groups); 211 } 212 } 213 214 if (groupNames.length == 0) { 215 console.error("The current test type wasn't present in any groups:", testType); 216 return groupNames; 217 } 218 219 var groupNames = groupNames.reduce(function(prev, curr) { 220 if (prev.indexOf(curr) == -1) { 221 prev.push(curr); 222 } 223 return prev; 224 }, []); 225 226 return groupNames; 227} 228 229})(); 230