3 let assert = require('assert');
5 require('../tools/js/v3-models.js');
6 require('./resources/mock-remote-api.js');
7 require('./resources/mock-v3-models.js');
9 let BuildbotBuildEntry = require('../tools/js/buildbot-syncer.js').BuildbotBuildEntry;
10 let BuildbotSyncer = require('../tools/js/buildbot-syncer.js').BuildbotSyncer;
12 function sampleiOSConfig()
18 'desired_image': {'root': 'iOS'},
19 'roots_dict': {'rootsExcluding': ['iOS']}
21 'slaveArgument': 'slavename',
22 'buildRequestArgument': 'build_request_id'
26 'test': ['Speedometer'],
27 'arguments': {'test_name': 'speedometer'}
30 'test': ['JetStream'],
31 'arguments': {'test_name': 'jetstream'}
34 "test": ["Dromaeo", "DOM Core Tests"],
35 "arguments": {"tests": "dromaeo-dom"}
40 'builder': 'ABTest-iPhone-RunBenchmark-Tests',
41 'arguments': { 'forcescheduler': 'ABTest-iPhone-RunBenchmark-Tests-ForceScheduler' }
44 'builder': 'ABTest-iPad-RunBenchmark-Tests',
45 'arguments': { 'forcescheduler': 'ABTest-iPad-RunBenchmark-Tests-ForceScheduler' }
49 {'type': 'speedometer', 'builder': 'iPhone-bench', 'platform': 'iPhone'},
50 {'type': 'jetstream', 'builder': 'iPhone-bench', 'platform': 'iPhone'},
51 {'type': 'dromaeo-dom', 'builder': 'iPhone-bench', 'platform': 'iPhone'},
53 {'type': 'speedometer', 'builder': 'iPad-bench', 'platform': 'iPad'},
54 {'type': 'jetstream', 'builder': 'iPad-bench', 'platform': 'iPad'},
59 let sampleRootSetData = {
62 'time': 1456955807334,
63 'repository': 'WebKit',
68 'time': 1456931874000,
69 'repository': 'Shared',
74 function createSampleBuildRequest()
76 let rootSet = RootSet.ensureSingleton('4197', {roots: [
77 {'id': '111127', 'time': 1456955807334, 'repository': webkit, 'revision': '197463'},
78 {'id': '111237', 'time': 1456931874000, 'repository': sharedRepository, 'revision': '80229'},
79 {'id': '88930', 'time': 0, 'repository': ios, 'revision': '13A452'},
82 let request = BuildRequest.ensureSingleton('16733', {'rootSet': rootSet, 'status': 'pending'});
86 function samplePendingBuild(buildRequestId)
89 'builderName': 'ABTest-iPad-RunBenchmark-Tests',
92 ['build_request_id', buildRequestId || '16733', 'Force Build Form'],
93 ['desired_image', '13A452', 'Force Build Form'],
94 ['owner', '<unknown>', 'Force Build Form'],
95 ['test_name', 'speedometer', 'Force Build Form'],
96 ['reason', 'force build','Force Build Form'],
99 JSON.stringify(sampleRootSetData),
102 ['scheduler', 'ABTest-iPad-RunBenchmark-Tests-ForceScheduler', 'Scheduler']
107 'codebase': 'compiler-rt',
113 'submittedAt': 1458704983
117 function sampleInProgressBuild()
121 'builderName': 'ABTest-iPad-RunBenchmark-Tests',
123 'eta': 0.26548067698460565,
124 'expectations': [['output', 845, 1315.0]],
128 'logs': [['stdio', 'https://build.webkit.org/builders/ABTest-iPad-RunBenchmark-Tests/builds/614/steps/Some%20step/logs/stdio']],
130 'results': [null,[]],
134 'times': [1458718657.581628, null],
137 'eta': 6497.991612434387,
138 'logs': [['stdio','https://build.webkit.org/builders/ABTest-iPad-RunBenchmark-Tests/builds/614/steps/shell/logs/stdio']],
141 ['build_request_id', '16733', 'Force Build Form'],
142 ['buildername', 'ABTest-iPad-RunBenchmark-Tests', 'Builder'],
143 ['buildnumber', 614, 'Build'],
144 ['desired_image', '13A452', 'Force Build Form'],
145 ['owner', '<unknown>', 'Force Build Form'],
146 ['reason', 'force build', 'Force Build Form'],
147 ['roots_dict', JSON.stringify(sampleRootSetData), 'Force Build Form'],
148 ['scheduler', 'ABTest-iPad-RunBenchmark-Tests-ForceScheduler', 'Scheduler'],
149 ['slavename', 'ABTest-iPad-0', 'BuildSlave'],
151 'reason': 'A build was forced by \'<unknown>\': force build',
153 'slave': 'ABTest-iPad-0',
154 'sourceStamps': [{'branch': '', 'changes': [], 'codebase': 'compiler-rt', 'hasPatch': false, 'project': '', 'repository': '', 'revision': ''}],
158 'expectations': [['output',2309,2309.0]],
162 'logs': [['stdio', 'https://build.webkit.org/builders/ABTest-iPad-RunBenchmark-Tests/builds/614/steps/shell/logs/stdio']],
163 'name': 'Finished step',
168 'times': [1458718655.419865, 1458718655.453633],
172 'eta': 0.26548067698460565,
173 'expectations': [['output', 845, 1315.0]],
177 'logs': [['stdio', 'https://build.webkit.org/builders/ABTest-iPad-RunBenchmark-Tests/builds/614/steps/Some%20step/logs/stdio']],
179 'results': [null,[]],
183 'times': [1458718657.581628, null],
188 'expectations': [['output', null, null]],
193 'name': 'Some other step',
194 'results': [null, []],
198 'times': [null, null],
203 'times': [1458718655.415821, null]
207 function sampleFinishedBuild(buildRequestId)
211 'builderName': 'ABTest-iPad-RunBenchmark-Tests',
214 'logs': [['stdio','https://build.webkit.org/builders/ABTest-iPad-RunBenchmark-Tests/builds/1755/steps/shell/logs/stdio']],
217 ['build_request_id', buildRequestId || '18935', 'Force Build Form'],
218 ['buildername', 'ABTest-iPad-RunBenchmark-Tests', 'Builder'],
219 ['buildnumber', 1755, 'Build'],
220 ['desired_image', '13A452', 'Force Build Form'],
221 ['owner', '<unknown>', 'Force Build Form'],
222 ['reason', 'force build', 'Force Build Form'],
223 ['roots_dict', JSON.stringify(sampleRootSetData), 'Force Build Form'],
224 ['scheduler', 'ABTest-iPad-RunBenchmark-Tests-ForceScheduler', 'Scheduler'],
225 ['slavename', 'ABTest-iPad-0', 'BuildSlave'],
227 'reason': 'A build was forced by \'<unknown>\': force build',
229 'slave': 'ABTest-iPad-0',
230 'sourceStamps': [{'branch': '', 'changes': [], 'codebase': 'compiler-rt', 'hasPatch': false, 'project': '', 'repository': '', 'revision': ''}],
234 'expectations': [['output',2309,2309.0]],
238 'logs': [['stdio', 'https://build.webkit.org/builders/ABTest-iPad-RunBenchmark-Tests/builds/614/steps/shell/logs/stdio']],
239 'name': 'Finished step',
244 'times': [1458718655.419865, 1458718655.453633],
249 'expectations': [['output', 845, 1315.0]],
253 'logs': [['stdio', 'https://build.webkit.org/builders/ABTest-iPad-RunBenchmark-Tests/builds/614/steps/Some%20step/logs/stdio']],
255 'results': [null,[]],
259 'times': [1458718657.581628, null],
264 'expectations': [['output', null, null]],
269 'name': 'Some other step',
270 'results': [null, []],
274 'times': [null, null],
279 'times': [1458937478.25837, 1458946147.173785]
283 describe('BuildbotSyncer', function () {
284 describe('_loadConfig', function () {
286 function smallConfiguration()
289 'builder': 'some builder',
290 'platform': 'some platform',
291 'test': ['some test'],
293 'buildRequestArgument': 'id'};
296 it('should create BuildbotSyncer objects for a configuration that specify all required options', function () {
297 let syncers = BuildbotSyncer._loadConfig('http://build.webkit.org/', {'configurations': [smallConfiguration()]});
298 assert.equal(syncers.length, 1);
301 it('should throw when some required options are missing', function () {
302 assert.throws(function () {
303 let config = smallConfiguration();
304 delete config['builder'];
305 BuildbotSyncer._loadConfig('http://build.webkit.org/', {'configurations': [config]});
306 }, 'builder should be a required option');
307 assert.throws(function () {
308 let config = smallConfiguration();
309 delete config['platform'];
310 BuildbotSyncer._loadConfig('http://build.webkit.org/', {'configurations': [config]});
311 }, 'platform should be a required option');
312 assert.throws(function () {
313 let config = smallConfiguration();
314 delete config['test'];
315 BuildbotSyncer._loadConfig('http://build.webkit.org/', {'configurations': [config]});
316 }, 'test should be a required option');
317 assert.throws(function () {
318 let config = smallConfiguration();
319 delete config['arguments'];
320 BuildbotSyncer._loadConfig('http://build.webkit.org/', {'configurations': [config]});
322 assert.throws(function () {
323 let config = smallConfiguration();
324 delete config['buildRequestArgument'];
325 BuildbotSyncer._loadConfig('http://build.webkit.org/', {'configurations': [config]});
329 it('should throw when a test name is not an array of strings', function () {
330 assert.throws(function () {
331 let config = smallConfiguration();
332 config.test = 'some test';
333 BuildbotSyncer._loadConfig('http://build.webkit.org/', {'configurations': [config]});
335 assert.throws(function () {
336 let config = smallConfiguration();
338 BuildbotSyncer._loadConfig('http://build.webkit.org/', {'configurations': [config]});
342 it('should throw when arguments is not an object', function () {
343 assert.throws(function () {
344 let config = smallConfiguration();
345 config.arguments = 'hello';
346 BuildbotSyncer._loadConfig('http://build.webkit.org/', {'configurations': [config]});
350 it('should throw when arguments\'s values are malformed', function () {
351 assert.throws(function () {
352 let config = smallConfiguration();
353 config.arguments = {'some': {'root': 'some root', 'rootsExcluding': ['other root']}};
354 BuildbotSyncer._loadConfig('http://build.webkit.org/', {'configurations': [config]});
356 assert.throws(function () {
357 let config = smallConfiguration();
358 config.arguments = {'some': {'otherKey': 'some root'}};
359 BuildbotSyncer._loadConfig('http://build.webkit.org/', {'configurations': [config]});
361 assert.throws(function () {
362 let config = smallConfiguration();
363 config.arguments = {'some': {'root': ['a', 'b']}};
364 BuildbotSyncer._loadConfig('http://build.webkit.org/', {'configurations': [config]});
366 assert.throws(function () {
367 let config = smallConfiguration();
368 config.arguments = {'some': {'root': 1}};
369 BuildbotSyncer._loadConfig('http://build.webkit.org/', {'configurations': [config]});
371 assert.throws(function () {
372 let config = smallConfiguration();
373 config.arguments = {'some': {'rootsExcluding': 'a'}};
374 BuildbotSyncer._loadConfig('http://build.webkit.org/', {'configurations': [config]});
376 assert.throws(function () {
377 let config = smallConfiguration();
378 config.arguments = {'some': {'rootsExcluding': [1]}};
379 BuildbotSyncer._loadConfig('http://build.webkit.org/', {'configurations': [config]});
383 it('should create BuildbotSyncer objects for valid configurations', function () {
384 let syncers = BuildbotSyncer._loadConfig('http://build.webkit.org/', sampleiOSConfig());
385 assert.equal(syncers.length, 5);
386 assert.ok(syncers[0] instanceof BuildbotSyncer);
387 assert.ok(syncers[1] instanceof BuildbotSyncer);
388 assert.ok(syncers[2] instanceof BuildbotSyncer);
389 assert.ok(syncers[3] instanceof BuildbotSyncer);
390 assert.ok(syncers[4] instanceof BuildbotSyncer);
393 it('should parse builder names correctly', function () {
394 let syncers = BuildbotSyncer._loadConfig('http://build.webkit.org/', sampleiOSConfig());
395 assert.equal(syncers[0].builderName(), 'ABTest-iPhone-RunBenchmark-Tests');
396 assert.equal(syncers[1].builderName(), 'ABTest-iPhone-RunBenchmark-Tests');
397 assert.equal(syncers[2].builderName(), 'ABTest-iPhone-RunBenchmark-Tests');
398 assert.equal(syncers[3].builderName(), 'ABTest-iPad-RunBenchmark-Tests');
399 assert.equal(syncers[4].builderName(), 'ABTest-iPad-RunBenchmark-Tests');
402 it('should parse platform names correctly', function () {
403 let syncers = BuildbotSyncer._loadConfig('http://build.webkit.org/', sampleiOSConfig());
404 assert.equal(syncers[0].platformName(), 'iPhone');
405 assert.equal(syncers[1].platformName(), 'iPhone');
406 assert.equal(syncers[2].platformName(), 'iPhone');
407 assert.equal(syncers[3].platformName(), 'iPad');
408 assert.equal(syncers[4].platformName(), 'iPad');
411 it('should parse test names correctly', function () {
412 let syncers = BuildbotSyncer._loadConfig('http://build.webkit.org/', sampleiOSConfig());
413 assert.deepEqual(syncers[0].testPath(), ['Speedometer']);
414 assert.deepEqual(syncers[1].testPath(), ['JetStream']);
415 assert.deepEqual(syncers[2].testPath(), ['Dromaeo', 'DOM Core Tests']);
416 assert.deepEqual(syncers[3].testPath(), ['Speedometer']);
417 assert.deepEqual(syncers[4].testPath(), ['JetStream']);
421 describe('_propertiesForBuildRequest', function () {
422 it('should include all properties specified in a given configuration', function () {
423 let syncers = BuildbotSyncer._loadConfig('http://build.webkit.org/', sampleiOSConfig());
424 let properties = syncers[0]._propertiesForBuildRequest(createSampleBuildRequest());
425 assert.deepEqual(Object.keys(properties), ['desired_image', 'roots_dict', 'test_name', 'forcescheduler', 'build_request_id']);
428 it('should preserve non-parametric property values', function () {
429 let syncers = BuildbotSyncer._loadConfig('http://build.webkit.org/', sampleiOSConfig());
430 let properties = syncers[0]._propertiesForBuildRequest(createSampleBuildRequest());
431 assert.equal(properties['test_name'], 'speedometer');
432 assert.equal(properties['forcescheduler'], 'ABTest-iPhone-RunBenchmark-Tests-ForceScheduler');
434 properties = syncers[1]._propertiesForBuildRequest(createSampleBuildRequest());
435 assert.equal(properties['test_name'], 'jetstream');
436 assert.equal(properties['forcescheduler'], 'ABTest-iPhone-RunBenchmark-Tests-ForceScheduler');
439 it('should resolve "root"', function () {
440 let syncers = BuildbotSyncer._loadConfig('http://build.webkit.org/', sampleiOSConfig());
441 let properties = syncers[0]._propertiesForBuildRequest(createSampleBuildRequest());
442 assert.equal(properties['desired_image'], '13A452');
445 it('should resolve "rootsExcluding"', function () {
446 let syncers = BuildbotSyncer._loadConfig('http://build.webkit.org/', sampleiOSConfig());
447 let properties = syncers[0]._propertiesForBuildRequest(createSampleBuildRequest());
448 assert.equal(properties['roots_dict'], JSON.stringify(sampleRootSetData));
451 it('should set the property for the build request id', function () {
452 let syncers = BuildbotSyncer._loadConfig('http://build.webkit.org/', sampleiOSConfig());
453 let properties = syncers[0]._propertiesForBuildRequest(createSampleBuildRequest());
454 assert.equal(properties['build_request_id'], createSampleBuildRequest().id());
458 describe('pullBuildbot', function () {
459 it('should fetch pending builds from the right URL', function () {
460 let syncer = BuildbotSyncer._loadConfig('http://build.webkit.org', sampleiOSConfig())[3];
461 assert.equal(syncer.builderName(), 'ABTest-iPad-RunBenchmark-Tests');
462 let expectedURL = 'http://build.webkit.org/json/builders/ABTest-iPad-RunBenchmark-Tests/pendingBuilds';
463 assert.equal(syncer.urlForPendingBuildsJSON(), expectedURL);
464 syncer.pullBuildbot();
465 assert.equal(requests.length, 1);
466 assert.equal(requests[0].url, expectedURL);
469 it('should fetch recent builds once pending builds have been fetched', function (done) {
470 let syncer = BuildbotSyncer._loadConfig('http://build.webkit.org', sampleiOSConfig())[3];
471 assert.equal(syncer.builderName(), 'ABTest-iPad-RunBenchmark-Tests');
473 syncer.pullBuildbot(1);
474 assert.equal(requests.length, 1);
475 assert.equal(requests[0].url, 'http://build.webkit.org/json/builders/ABTest-iPad-RunBenchmark-Tests/pendingBuilds');
476 requests[0].resolve([]);
477 Promise.resolve().then(function () {
478 assert.equal(requests.length, 2);
479 assert.equal(requests[1].url, 'http://build.webkit.org/json/builders/ABTest-iPad-RunBenchmark-Tests/builds/?select=-1');
484 it('should fetch the right number of recent builds', function (done) {
485 let syncer = BuildbotSyncer._loadConfig('http://build.webkit.org', sampleiOSConfig())[3];
487 syncer.pullBuildbot(3);
488 assert.equal(requests.length, 1);
489 assert.equal(requests[0].url, 'http://build.webkit.org/json/builders/ABTest-iPad-RunBenchmark-Tests/pendingBuilds');
490 requests[0].resolve([]);
491 Promise.resolve().then(function () {
492 assert.equal(requests.length, 2);
493 assert.equal(requests[1].url, 'http://build.webkit.org/json/builders/ABTest-iPad-RunBenchmark-Tests/builds/?select=-1&select=-2&select=-3');
498 it('should create BuildbotBuildEntry for pending builds', function (done) {
499 let syncer = BuildbotSyncer._loadConfig('http://build.webkit.org', sampleiOSConfig())[3];
500 let promise = syncer.pullBuildbot();
501 requests[0].resolve([samplePendingBuild()]);
502 promise.then(function (entries) {
503 assert.deepEqual(Object.keys(entries), ['16733']);
504 let entry = entries['16733'];
505 assert.ok(entry instanceof BuildbotBuildEntry);
506 assert.ok(!entry.buildNumber());
507 assert.ok(!entry.slaveName());
508 assert.equal(entry.buildRequestId(), 16733);
509 assert.ok(entry.isPending());
510 assert.ok(!entry.isInProgress());
511 assert.ok(!entry.hasFinished());
512 assert.equal(entry.url(), 'http://build.webkit.org/builders/ABTest-iPad-RunBenchmark-Tests/');
517 it('should create BuildbotBuildEntry for in-progress builds', function (done) {
518 let syncer = BuildbotSyncer._loadConfig('http://build.webkit.org', sampleiOSConfig())[3];
520 let promise = syncer.pullBuildbot(1);
521 assert.equal(requests.length, 1);
522 requests[0].resolve([]);
523 Promise.resolve().then(function () {
524 assert.equal(requests.length, 2);
525 requests[1].resolve({[-1]: sampleInProgressBuild()});
528 promise.then(function (entries) {
529 assert.deepEqual(Object.keys(entries), ['16733']);
530 let entry = entries['16733'];
531 assert.ok(entry instanceof BuildbotBuildEntry);
532 assert.equal(entry.buildNumber(), 614);
533 assert.equal(entry.slaveName(), 'ABTest-iPad-0');
534 assert.equal(entry.buildRequestId(), 16733);
535 assert.ok(!entry.isPending());
536 assert.ok(entry.isInProgress());
537 assert.ok(!entry.hasFinished());
538 assert.equal(entry.url(), 'http://build.webkit.org/builders/ABTest-iPad-RunBenchmark-Tests/builds/614');
543 it('should create BuildbotBuildEntry for finished builds', function (done) {
544 let syncer = BuildbotSyncer._loadConfig('http://build.webkit.org', sampleiOSConfig())[3];
546 let promise = syncer.pullBuildbot(1);
547 assert.equal(requests.length, 1);
548 requests[0].resolve([]);
549 Promise.resolve().then(function () {
550 assert.equal(requests.length, 2);
551 requests[1].resolve({[-1]: sampleFinishedBuild()});
554 promise.then(function (entries) {
555 assert.deepEqual(Object.keys(entries), ['18935']);
556 let entry = entries['18935'];
557 assert.ok(entry instanceof BuildbotBuildEntry);
558 assert.equal(entry.buildNumber(), 1755);
559 assert.equal(entry.slaveName(), 'ABTest-iPad-0');
560 assert.equal(entry.buildRequestId(), 18935);
561 assert.ok(!entry.isPending());
562 assert.ok(!entry.isInProgress());
563 assert.ok(entry.hasFinished());
564 assert.equal(entry.url(), 'http://build.webkit.org/builders/ABTest-iPad-RunBenchmark-Tests/builds/1755');
569 it('should create BuildbotBuildEntry for mixed pending, in-progress, finished, and missing builds', function (done) {
570 let syncer = BuildbotSyncer._loadConfig('http://build.webkit.org', sampleiOSConfig())[3];
572 let promise = syncer.pullBuildbot(5);
573 assert.equal(requests.length, 1);
575 requests[0].resolve([samplePendingBuild(123, 456)]);
577 Promise.resolve().then(function () {
578 assert.equal(requests.length, 2);
579 requests[1].resolve({[-1]: sampleFinishedBuild(), [-2]: {'error': 'Not available'}, [-4]: sampleInProgressBuild()});
582 promise.then(function (entries) {
583 assert.deepEqual(Object.keys(entries), ['123', '16733', '18935']);
585 let entry = entries['123'];
586 assert.ok(entry instanceof BuildbotBuildEntry);
587 assert.equal(entry.buildNumber(), null);
588 assert.equal(entry.slaveName(), null);
589 assert.equal(entry.buildRequestId(), 123);
590 assert.ok(entry.isPending());
591 assert.ok(!entry.isInProgress());
592 assert.ok(!entry.hasFinished());
593 assert.equal(entry.url(), 'http://build.webkit.org/builders/ABTest-iPad-RunBenchmark-Tests/');
595 entry = entries['16733'];
596 assert.ok(entry instanceof BuildbotBuildEntry);
597 assert.equal(entry.buildNumber(), 614);
598 assert.equal(entry.slaveName(), 'ABTest-iPad-0');
599 assert.equal(entry.buildRequestId(), 16733);
600 assert.ok(!entry.isPending());
601 assert.ok(entry.isInProgress());
602 assert.ok(!entry.hasFinished());
603 assert.equal(entry.url(), 'http://build.webkit.org/builders/ABTest-iPad-RunBenchmark-Tests/builds/614');
605 entry = entries['18935'];
606 assert.ok(entry instanceof BuildbotBuildEntry);
607 assert.equal(entry.buildNumber(), 1755);
608 assert.equal(entry.slaveName(), 'ABTest-iPad-0');
609 assert.equal(entry.buildRequestId(), 18935);
610 assert.ok(!entry.isPending());
611 assert.ok(!entry.isInProgress());
612 assert.ok(entry.hasFinished());
613 assert.equal(entry.url(), 'http://build.webkit.org/builders/ABTest-iPad-RunBenchmark-Tests/builds/1755');
619 it('should override BuildbotBuildEntry for pending builds by in-progress builds', function (done) {
620 let syncer = BuildbotSyncer._loadConfig('http://build.webkit.org', sampleiOSConfig())[3];
622 let promise = syncer.pullBuildbot(5);
623 assert.equal(requests.length, 1);
625 requests[0].resolve([samplePendingBuild()]);
627 Promise.resolve().then(function () {
628 assert.equal(requests.length, 2);
629 requests[1].resolve({[-1]: sampleInProgressBuild()});
632 promise.then(function (entries) {
633 assert.deepEqual(Object.keys(entries), ['16733']);
635 let entry = entries['16733'];
636 assert.ok(entry instanceof BuildbotBuildEntry);
637 assert.equal(entry.buildNumber(), 614);
638 assert.equal(entry.slaveName(), 'ABTest-iPad-0');
639 assert.equal(entry.buildRequestId(), 16733);
640 assert.ok(!entry.isPending());
641 assert.ok(entry.isInProgress());
642 assert.ok(!entry.hasFinished());
643 assert.equal(entry.url(), 'http://build.webkit.org/builders/ABTest-iPad-RunBenchmark-Tests/builds/614');
649 it('should override BuildbotBuildEntry for pending builds by finished builds', function (done) {
650 let syncer = BuildbotSyncer._loadConfig('http://build.webkit.org', sampleiOSConfig())[3];
652 let promise = syncer.pullBuildbot(5);
653 assert.equal(requests.length, 1);
655 requests[0].resolve([samplePendingBuild()]);
657 Promise.resolve().then(function () {
658 assert.equal(requests.length, 2);
659 requests[1].resolve({[-1]: sampleFinishedBuild(16733)});
662 promise.then(function (entries) {
663 assert.deepEqual(Object.keys(entries), ['16733']);
665 let entry = entries['16733'];
666 assert.ok(entry instanceof BuildbotBuildEntry);
667 assert.equal(entry.buildNumber(), 1755);
668 assert.equal(entry.slaveName(), 'ABTest-iPad-0');
669 assert.equal(entry.buildRequestId(), 16733);
670 assert.ok(!entry.isPending());
671 assert.ok(!entry.isInProgress());
672 assert.ok(entry.hasFinished());
673 assert.equal(entry.url(), 'http://build.webkit.org/builders/ABTest-iPad-RunBenchmark-Tests/builds/1755');