Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(6)

Side by Side Diff: Tools/BuildSlaveSupport/build.webkit.org-config/public_html/TestFailures/scripts/base.js

Issue 13712005: Move GardeningServer out of BuildSlaveSupport (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: Created 7 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
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
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
14 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23 * THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26 var base = base || {};
27
28 (function(){
29
30 // Safari 5.1 lacks Function.prototype.bind.
31 if (!('bind' in Function.prototype)) {
32 Function.prototype.bind = function(thisObject) {
33 var method = this;
34 var boundArguments = [];
35 for (var i = 1; i < arguments.length; ++i) {
36 boundArguments.push(arguments[i]);
37 }
38 return function() {
39 var actualParameters = [];
40 for (var i = 0; i < boundArguments.length; ++i) {
41 actualParameters.push(boundArguments[i]);
42 }
43 for (var i = 0; i < arguments.length; ++i) {
44 actualParameters.push(arguments[i]);
45 }
46 return method.apply(thisObject, actualParameters);
47 }
48 }
49 }
50
51 base.asInteger = function(stringOrInteger)
52 {
53 if (typeof stringOrInteger == 'string')
54 return parseInt(stringOrInteger);
55 return stringOrInteger;
56 };
57
58 base.endsWith = function(string, suffix)
59 {
60 if (suffix.length > string.length)
61 return false;
62 var expectedIndex = string.length - suffix.length;
63 return string.lastIndexOf(suffix) == expectedIndex;
64 };
65
66 base.repeatString = function(string, count)
67 {
68 return new Array(count + 1).join(string);
69 };
70
71 base.joinPath = function(parent, child)
72 {
73 if (parent.length == 0)
74 return child;
75 return parent + '/' + child;
76 };
77
78 base.dirName = function(path)
79 {
80 var directoryIndex = path.lastIndexOf('/');
81 if (directoryIndex == -1)
82 return path;
83 return path.substr(0, directoryIndex);
84 };
85
86 base.trimExtension = function(url)
87 {
88 var index = url.lastIndexOf('.');
89 if (index == -1)
90 return url;
91 return url.substr(0, index);
92 }
93
94 base.uniquifyArray = function(array)
95 {
96 var seen = {};
97 var result = [];
98 $.each(array, function(index, value) {
99 if (seen[value])
100 return;
101 seen[value] = true;
102 result.push(value);
103 });
104 return result;
105 };
106
107 base.flattenArray = function(arrayOfArrays)
108 {
109 if (!arrayOfArrays.length)
110 return [];
111 return arrayOfArrays.reduce(function(left, right) {
112 return left.concat(right);
113 });
114 };
115
116 base.filterDictionary = function(dictionary, predicate)
117 {
118 var result = {};
119
120 for (var key in dictionary) {
121 if (predicate(key))
122 result[key] = dictionary[key];
123 }
124
125 return result;
126 };
127
128 base.mapDictionary = function(dictionary, functor)
129 {
130 var result = {};
131
132 for (var key in dictionary) {
133 var value = functor(dictionary[key]);
134 if (typeof value !== 'undefined')
135 result[key] = value;
136 }
137
138 return result;
139 };
140
141 base.filterTree = function(tree, isLeaf, predicate)
142 {
143 var filteredTree = {};
144
145 function walkSubtree(subtree, directory)
146 {
147 for (var childName in subtree) {
148 var child = subtree[childName];
149 var childPath = base.joinPath(directory, childName);
150 if (isLeaf(child)) {
151 if (predicate(child))
152 filteredTree[childPath] = child;
153 continue;
154 }
155 walkSubtree(child, childPath);
156 }
157 }
158
159 walkSubtree(tree, '');
160 return filteredTree;
161 };
162
163 base.forEachDirectory = function(pathList, callback)
164 {
165 var pathsByDirectory = {};
166 pathList.forEach(function(path) {
167 var directory = base.dirName(path);
168 pathsByDirectory[directory] = pathsByDirectory[directory] || [];
169 pathsByDirectory[directory].push(path);
170 });
171 Object.keys(pathsByDirectory).sort().forEach(function(directory) {
172 var paths = pathsByDirectory[directory];
173 callback(directory + ' (' + paths.length + ' tests)', paths);
174 });
175 };
176
177 base.parseJSONP = function(jsonp)
178 {
179 var startIndex = jsonp.indexOf('(') + 1;
180 var endIndex = jsonp.lastIndexOf(')');
181 if (startIndex == 0 || endIndex == -1)
182 return {};
183 return JSON.parse(jsonp.substr(startIndex, endIndex - startIndex));
184 };
185
186 base.RequestTracker = function(requestsInFlight, callback, args)
187 {
188 this._requestsInFlight = requestsInFlight;
189 this._callback = callback;
190 this._args = args || [];
191 this._tryCallback();
192 };
193
194 base.RequestTracker.prototype = {
195 _tryCallback: function()
196 {
197 if (!this._requestsInFlight && this._callback)
198 this._callback.apply(null, this._args);
199 },
200 requestComplete: function()
201 {
202 --this._requestsInFlight;
203 this._tryCallback();
204 }
205 }
206
207 base.callInParallel = function(functionList, callback)
208 {
209 var requestTracker = new base.RequestTracker(functionList.length, callback);
210
211 $.each(functionList, function(index, func) {
212 func(function() {
213 requestTracker.requestComplete();
214 });
215 });
216 };
217
218 base.callInSequence = function(func, argumentList, callback)
219 {
220 var nextIndex = 0;
221
222 function callNext()
223 {
224 if (nextIndex >= argumentList.length) {
225 callback();
226 return;
227 }
228
229 func(argumentList[nextIndex++], callNext);
230 }
231
232 callNext();
233 };
234
235 base.CallbackIterator = function(callback, listOfArgumentArrays)
236 {
237 this._callback = callback;
238 this._nextIndex = 0;
239 this._listOfArgumentArrays = listOfArgumentArrays;
240 };
241
242 base.CallbackIterator.prototype.hasNext = function()
243 {
244 return this._nextIndex < this._listOfArgumentArrays.length;
245 };
246
247 base.CallbackIterator.prototype.hasPrevious = function()
248 {
249 return this._nextIndex - 2 >= 0;
250 };
251
252 base.CallbackIterator.prototype.callNext = function()
253 {
254 if (!this.hasNext())
255 return;
256 var args = this._listOfArgumentArrays[this._nextIndex];
257 this._nextIndex++;
258 this._callback.apply(null, args);
259 };
260
261 base.CallbackIterator.prototype.callPrevious = function()
262 {
263 if (!this.hasPrevious())
264 return;
265 var args = this._listOfArgumentArrays[this._nextIndex - 2];
266 this._nextIndex--;
267 this._callback.apply(null, args);
268 };
269
270 base.AsynchronousCache = function(fetch)
271 {
272 this._fetch = fetch;
273 this._dataCache = {};
274 this._callbackCache = {};
275 };
276
277 base.AsynchronousCache.prototype.get = function(key, callback)
278 {
279 var self = this;
280
281 if (self._dataCache[key]) {
282 // FIXME: Consider always calling callback asynchronously.
283 callback(self._dataCache[key]);
284 return;
285 }
286
287 if (key in self._callbackCache) {
288 self._callbackCache[key].push(callback);
289 return;
290 }
291
292 self._callbackCache[key] = [callback];
293
294 self._fetch.call(null, key, function(data) {
295 self._dataCache[key] = data;
296
297 var callbackList = self._callbackCache[key];
298 delete self._callbackCache[key];
299
300 callbackList.forEach(function(cachedCallback) {
301 cachedCallback(data);
302 });
303 });
304 };
305
306 base.AsynchronousCache.prototype.clear = function()
307 {
308 this._dataCache = {};
309 this._callbackCache = {};
310 }
311
312 /*
313 Maintains a dictionary of items, tracking their updates and removing items t hat haven't been updated.
314 An "update" is a call to the "update" method.
315 To remove stale items, call the "remove" method. It will remove all
316 items that have not been been updated since the last call of "remove".
317 */
318 base.UpdateTracker = function()
319 {
320 this._items = {};
321 this._updated = {};
322 }
323
324 base.UpdateTracker.prototype = {
325 /*
326 Update an {key}/{item} pair. You can make the dictionary act as a set an d
327 skip the {item}, in which case the {key} is also the {item}.
328 */
329 update: function(key, object)
330 {
331 object = object || key;
332 this._items[key] = object;
333 this._updated[key] = 1;
334 },
335 exists: function(key)
336 {
337 return !!this.get(key);
338 },
339 get: function(key)
340 {
341 return this._items[key];
342 },
343 length: function()
344 {
345 return Object.keys(this._items).length;
346 },
347 /*
348 Callback parameters are:
349 - item
350 - key
351 - updated, which is true if the item was updated after last purge() call .
352 */
353 forEach: function(callback, thisObject)
354 {
355 if (!callback)
356 return;
357
358 Object.keys(this._items).sort().forEach(function(key) {
359 var item = this._items[key];
360 callback.call(thisObject || item, item, key, !!this._updated[key]);
361 }, this);
362 },
363 purge: function(removeCallback, thisObject) {
364 removeCallback = removeCallback || function() {};
365 this.forEach(function(item, key, updated) {
366 if (updated)
367 return;
368 removeCallback.call(thisObject || item, item);
369 delete this._items[key];
370 }, this);
371 this._updated = {};
372 }
373 }
374
375 // Based on http://src.chromium.org/viewvc/chrome/trunk/src/chrome/browser/resou rces/shared/js/cr/ui.js
376 base.extends = function(base, prototype)
377 {
378 var extended = function() {
379 var element = typeof base == 'string' ? document.createElement(base) : b ase.call(this);
380 extended.prototype.__proto__ = element.__proto__;
381 element.__proto__ = extended.prototype;
382 var singleton = element.init && element.init.apply(element, arguments);
383 if (singleton)
384 return singleton;
385 return element;
386 }
387
388 extended.prototype = prototype;
389 return extended;
390 }
391
392 function createRelativeTimeDescriptor(divisorInMilliseconds, unit)
393 {
394 return function(delta) {
395 var deltaInUnits = delta / divisorInMilliseconds;
396 return (deltaInUnits).toFixed(0) + ' ' + unit + (deltaInUnits >= 1.5 ? ' s' : '') + ' ago';
397 }
398 }
399
400 var kMinuteInMilliseconds = 60 * 1000;
401 var kRelativeTimeSlots = [
402 {
403 maxMilliseconds: kMinuteInMilliseconds,
404 describe: function(delta) { return 'Just now'; }
405 },
406 {
407 maxMilliseconds: 60 * kMinuteInMilliseconds,
408 describe: createRelativeTimeDescriptor(kMinuteInMilliseconds, 'minute')
409 },
410 {
411 maxMilliseconds: 24 * 60 * kMinuteInMilliseconds,
412 describe: createRelativeTimeDescriptor(60 * kMinuteInMilliseconds, 'hour ')
413 },
414 {
415 maxMilliseconds: Number.MAX_VALUE,
416 describe: createRelativeTimeDescriptor(24 * 60 * kMinuteInMilliseconds, 'day')
417 }
418 ];
419
420 /*
421 Represent time as descriptive text, relative to now and gradually decreasing in precision:
422 delta < 1 minutes => Just Now
423 delta < 60 minutes => X minute[s] ago
424 delta < 24 hours => X hour[s] ago
425 delta < inf => X day[s] ago
426 */
427 base.relativizeTime = function(time)
428 {
429 var result;
430 var delta = new Date().getTime() - time;
431 kRelativeTimeSlots.some(function(slot) {
432 if (delta >= slot.maxMilliseconds)
433 return false;
434
435 result = slot.describe(delta);
436 return true;
437 });
438 return result;
439 }
440
441 base.getURLParameter = function(name)
442 {
443 var match = RegExp(name + '=' + '(.+?)(&|$)').exec(location.search);
444 if (!match)
445 return null;
446 return decodeURI(match[1])
447 }
448
449 base.underscoredBuilderName = function(builderName)
450 {
451 return builderName.replace(/[ .()]/g, '_');
452 }
453
454 base.createLinkNode = function(url, textContent, opt_target)
455 {
456 var link = document.createElement('a');
457 link.href = url;
458 if (opt_target)
459 link.target = opt_target;
460 link.appendChild(document.createTextNode(textContent));
461 return link;
462 }
463
464 })();
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698