REGRESSION(r230960): Browser tests under TimeSeriesChart fetchMeasurementSets all...
[WebKit-https.git] / Websites / perf.webkit.org / unit-tests / buildbot-syncer-tests.js
index 705be81..66cafc6 100644 (file)
@@ -3,11 +3,13 @@
 let assert = require('assert');
 
 require('../tools/js/v3-models.js');
-let MockRemoteAPI = require('./resources/mock-remote-api.js').MockRemoteAPI;
-let MockModels = require('./resources/mock-v3-models.js').MockModels;
+const BrowserPrivilegedAPI = require('../public/v3/privileged-api.js').PrivilegedAPI;
 
-let BuildbotBuildEntry = require('../tools/js/buildbot-syncer.js').BuildbotBuildEntry;
-let BuildbotSyncer = require('../tools/js/buildbot-syncer.js').BuildbotSyncer;
+const MockRemoteAPI = require('./resources/mock-remote-api.js').MockRemoteAPI;
+const MockModels = require('./resources/mock-v3-models.js').MockModels;
+
+const BuildbotBuildEntry = require('../tools/js/buildbot-syncer.js').BuildbotBuildEntry;
+const BuildbotSyncer = require('../tools/js/buildbot-syncer.js').BuildbotSyncer;
 
 function sampleiOSConfig()
 {
@@ -133,6 +135,7 @@ function smallConfiguration()
         'builders': {
             'some-builder': {
                 'builder': 'some builder',
+                'properties': {'forcescheduler': 'some-builder-ForceScheduler'}
             }
         },
         'testConfigurations': [{
@@ -153,68 +156,22 @@ function builderNameToIDMap()
         'iPhone AB Tests' : '104',
         'iPhone 2 AB Tests': '105',
         'iPad AB Tests': '106'
-    }    
+    };
 }
 
 function smallPendingBuild()
 {
-    return {
-        'builderName': 'some builder',
-        'builds': [],
-        'properties': [],
-        'source': {
-            'branch': '',
-            'changes': [],
-            'codebase': 'WebKit',
-            'hasPatch': false,
-            'project': '',
-            'repository': '',
-            'revision': ''
-        },
-    };
+    return samplePendingBuildRequests(null, null, null, "some builder");
 }
 
 function smallInProgressBuild()
 {
-    return {
-        'builderName': 'some builder',
-        'builds': [],
-        'properties': [],
-        'currentStep': { },
-        'eta': 123,
-        'number': 456,
-        'source': {
-            'branch': '',
-            'changes': [],
-            'codebase': 'WebKit',
-            'hasPatch': false,
-            'project': '',
-            'repository': '',
-            'revision': ''
-        },
-    };
+    return sampleInProgressBuild();
 }
 
 function smallFinishedBuild()
 {
-    return {
-        'builderName': 'some builder',
-        'builds': [],
-        'properties': [],
-        'currentStep': null,
-        'eta': null,
-        'number': 789,
-        'source': {
-            'branch': '',
-            'changes': [],
-            'codebase': 'WebKit',
-            'hasPatch': false,
-            'project': '',
-            'repository': '',
-            'revision': ''
-        },
-        'times': [0, 1],
-    };
+    return sampleFinishedBuild(null, null, "some builder");
 }
 
 function createSampleBuildRequest(platform, test)
@@ -295,200 +252,88 @@ function createSampleBuildRequestWithOwnedCommitAndPatch(platform, test, order)
         'commitSet': commitSet, 'status': 'pending', 'platform': platform, 'test': test, 'order': order});
 }
 
-function samplePendingBuild(buildRequestId, buildTime, slaveName)
+function samplePendingBuildRequestData(buildRequestId, buildTime, workerName, builderId)
 {
     return {
-        'builderName': 'ABTest-iPad-RunBenchmark-Tests',
-        'builds': [],
-        'properties': [
-            ['build_request_id', buildRequestId || '16733', 'Force Build Form'],
-            ['desired_image', '13A452', 'Force Build Form'],
-            ['owner', '<unknown>', 'Force Build Form'],
-            ['test_name', 'speedometer', 'Force Build Form'],
-            ['reason', 'force build','Force Build Form'],
-            ['slavename', slaveName, ''],
-            ['scheduler', 'ABTest-iPad-RunBenchmark-Tests-ForceScheduler', 'Scheduler']
-        ],
-        'source': {
-            'branch': '',
-            'changes': [],
-            'codebase': 'compiler-rt',
-            'hasPatch': false,
-            'project': '',
-            'repository': '',
-            'revision': ''
-        },
-        'submittedAt': buildTime || 1458704983
+        "builderid": builderId || 102,
+        "buildrequestid": 17,
+        "buildsetid": 894720,
+        "claimed": false,
+        "claimed_at": null,
+        "claimed_by_masterid": null,
+        "complete": false,
+        "complete_at": null,
+        "priority": 0,
+        "results": -1,
+        "submitted_at": buildTime || 1458704983,
+        "waited_for": false,
+        "properties": {
+            "build_request_id": [buildRequestId || 16733, "Force Build Form"],
+            "scheduler": ["ABTest-iPad-RunBenchmark-Tests-ForceScheduler", "Scheduler"],
+            "slavename": [workerName, "Worker (deprecated)"],
+            "workername": [workerName, "Worker"]
+        }
     };
 }
 
-function sampleInProgressBuild(slaveName)
+function samplePendingBuildRequests(buildRequestId, buildTime, workerName, builderName)
 {
     return {
-        'blame': [],
-        'builderName': 'ABTest-iPad-RunBenchmark-Tests',
-        'currentStep': {
-            'eta': 0.26548067698460565,
-            'expectations': [['output', 845, 1315.0]],
-            'hidden': false,
-            'isFinished': false,
-            'isStarted': true,
-            'logs': [['stdio', 'https://build.webkit.org/builders/ABTest-iPad-RunBenchmark-Tests/builds/614/steps/Some%20step/logs/stdio']],
-            'name': 'Some step',
-            'results': [null,[]],
-            'statistics': {},
-            'step_number': 1,
-            'text': [''],
-            'times': [1458718657.581628, null],
-            'urls': {}
-        },
-        'eta': 6497.991612434387,
-        'logs': [['stdio','https://build.webkit.org/builders/ABTest-iPad-RunBenchmark-Tests/builds/614/steps/shell/logs/stdio']],
-        'number': 614,
-        'properties': [
-            ['build_request_id', '16733', 'Force Build Form'],
-            ['buildername', 'ABTest-iPad-RunBenchmark-Tests', 'Builder'],
-            ['buildnumber', 614, 'Build'],
-            ['desired_image', '13A452', 'Force Build Form'],
-            ['owner', '<unknown>', 'Force Build Form'],
-            ['reason', 'force build', 'Force Build Form'],
-            ['scheduler', 'ABTest-iPad-RunBenchmark-Tests-ForceScheduler', 'Scheduler'],
-            ['slavename', slaveName || 'ABTest-iPad-0', 'BuildSlave'],
-        ],
-        'reason': 'A build was forced by \'<unknown>\': force build',
-        'results': null,
-        'slave': 'ABTest-iPad-0',
-        'sourceStamps': [{'branch': '', 'changes': [], 'codebase': 'compiler-rt', 'hasPatch': false, 'project': '', 'repository': '', 'revision': ''}],
-        'steps': [
-            {
-                'eta': null,
-                'expectations': [['output',2309,2309.0]],
-                'hidden': false,
-                'isFinished': true,
-                'isStarted': true,
-                'logs': [['stdio', 'https://build.webkit.org/builders/ABTest-iPad-RunBenchmark-Tests/builds/614/steps/shell/logs/stdio']],
-                'name': 'Finished step',
-                'results': [0, []],
-                'statistics': {},
-                'step_number': 0,
-                'text': [''],
-                'times': [1458718655.419865, 1458718655.453633],
-                'urls': {}
-            },
-            {
-                'eta': 0.26548067698460565,
-                'expectations': [['output', 845, 1315.0]],
-                'hidden': false,
-                'isFinished': false,
-                'isStarted': true,
-                'logs': [['stdio', 'https://build.webkit.org/builders/ABTest-iPad-RunBenchmark-Tests/builds/614/steps/Some%20step/logs/stdio']],
-                'name': 'Some step',
-                'results': [null,[]],
-                'statistics': {},
-                'step_number': 1,
-                'text': [''],
-                'times': [1458718657.581628, null],
-                'urls': {}
-            },
-            {
-                'eta': null,
-                'expectations': [['output', null, null]],
-                'hidden': false,
-                'isFinished': false,
-                'isStarted': false,
-                'logs': [],
-                'name': 'Some other step',
-                'results': [null, []],
-                'statistics': {},
-                'step_number': 2,
-                'text': [],
-                'times': [null, null],
-                'urls': {}
-            },
-        ],
-        'text': [],
-        'times': [1458718655.415821, null]
+        "buildrequests" : [samplePendingBuildRequestData(buildRequestId, buildTime, workerName, builderNameToIDMap()[builderName])]
     };
 }
 
-function sampleFinishedBuild(buildRequestId, slaveName)
+function sampleBuildData(workerName, isComplete, buildRequestId, buildNumber, builderId)
 {
     return {
-        'blame': [],
-        'builderName': 'ABTest-iPad-RunBenchmark-Tests',
-        'currentStep': null,
-        'eta': null,
-        'logs': [['stdio','https://build.webkit.org/builders/ABTest-iPad-RunBenchmark-Tests/builds/1755/steps/shell/logs/stdio']],
-        'number': 1755,
-        'properties': [
-            ['build_request_id', buildRequestId || '18935', 'Force Build Form'],
-            ['buildername', 'ABTest-iPad-RunBenchmark-Tests', 'Builder'],
-            ['buildnumber', 1755, 'Build'],
-            ['desired_image', '13A452', 'Force Build Form'],
-            ['owner', '<unknown>', 'Force Build Form'],
-            ['reason', 'force build', 'Force Build Form'],
-            ['scheduler', 'ABTest-iPad-RunBenchmark-Tests-ForceScheduler', 'Scheduler'],
-            ['slavename', slaveName || 'ABTest-iPad-0', 'BuildSlave'],
-        ],
-        'reason': 'A build was forced by \'<unknown>\': force build',
-        'results': 2,
-        'slave': 'ABTest-iPad-0',
-        'sourceStamps': [{'branch': '', 'changes': [], 'codebase': 'compiler-rt', 'hasPatch': false, 'project': '', 'repository': '', 'revision': ''}],
-        'steps': [
-            {
-                'eta': null,
-                'expectations': [['output',2309,2309.0]],
-                'hidden': false,
-                'isFinished': true,
-                'isStarted': true,
-                'logs': [['stdio', 'https://build.webkit.org/builders/ABTest-iPad-RunBenchmark-Tests/builds/614/steps/shell/logs/stdio']],
-                'name': 'Finished step',
-                'results': [0, []],
-                'statistics': {},
-                'step_number': 0,
-                'text': [''],
-                'times': [1458718655.419865, 1458718655.453633],
-                'urls': {}
-            },
-            {
-                'eta': null,
-                'expectations': [['output', 845, 1315.0]],
-                'hidden': false,
-                'isFinished': true,
-                'isStarted': true,
-                'logs': [['stdio', 'https://build.webkit.org/builders/ABTest-iPad-RunBenchmark-Tests/builds/614/steps/Some%20step/logs/stdio']],
-                'name': 'Some step',
-                'results': [null,[]],
-                'statistics': {},
-                'step_number': 1,
-                'text': [''],
-                'times': [1458718657.581628, null],
-                'urls': {}
-            },
-            {
-                'eta': null,
-                'expectations': [['output', null, null]],
-                'hidden': false,
-                'isFinished': true,
-                'isStarted': true,
-                'logs': [],
-                'name': 'Some other step',
-                'results': [null, []],
-                'statistics': {},
-                'step_number': 2,
-                'text': [],
-                'times': [null, null],
-                'urls': {}
-            },
-        ],
-        'text': [],
-        'times': [1458937478.25837, 1458946147.173785]
+        "builderid": builderId || 102,
+        "number": buildNumber || 614,
+        "buildrequestid": 17,
+        "complete": isComplete,
+        "complete_at": null,
+        "buildid": 418744,
+        "masterid": 1,
+        "results": null,
+        "started_at": 1513725109,
+        "state_string": "building",
+        "workerid": 41,
+        "properties": {
+            "build_request_id": [buildRequestId || 16733, "Force Build Form"],
+            "platform": ["mac", "Unknown"],
+            "scheduler": ["ABTest-iPad-RunBenchmark-Tests-ForceScheduler", "Scheduler"],
+            "slavename": [workerName || "ABTest-iPad-0", "Worker (deprecated)"],
+            "workername": [workerName || "ABTest-iPad-0", "Worker"]
+        }
+    };
+}
+
+function sampleInProgressBuildData(workerName)
+{
+    return sampleBuildData(workerName, false);
+}
+
+function sampleInProgressBuild(workerName)
+{
+    return {
+        "builds": [sampleInProgressBuildData(workerName)]
+    };
+}
+
+function sampleFinishedBuildData(buildRequestId, workerName, builderName)
+{
+    return sampleBuildData(workerName, true, buildRequestId || 18935, 1755, builderNameToIDMap()[builderName]);
+}
+
+function sampleFinishedBuild(buildRequestId, workerName, builderName)
+{
+    return {
+        "builds": [sampleFinishedBuildData(buildRequestId, workerName, builderName)]
     };
 }
 
 describe('BuildbotSyncer', () => {
     MockModels.inject();
-    let requests = MockRemoteAPI.inject('http://build.webkit.org');
+    const requests = MockRemoteAPI.inject('http://build.webkit.org', BrowserPrivilegedAPI);
 
     describe('_loadConfig', () => {
 
@@ -1021,6 +866,7 @@ describe('BuildbotSyncer', () => {
                     'webkit': {'revision': 'WebKit'},
                     'webkit-patch': {'patch': 'WebKit'},
                     'checkbox': {'ifRepositorySet': ['WebKit'], 'value': 'build-webkit'},
+                    'build-webkit': {'ifRepositorySet': ['WebKit'], 'value': true},
                     'shared': {'revision': 'Shared'},
                 },
                 'acceptsRoots': true,
@@ -1031,6 +877,7 @@ describe('BuildbotSyncer', () => {
             assert.equal(properties['webkit'], '197463');
             assert.equal(properties['webkit-patch'], 'http://build.webkit.org/api/uploaded-file/453.dat');
             assert.equal(properties['checkbox'], 'build-webkit');
+            assert.equal(properties['build-webkit'], true);
         });
 
         it('should resolve "ifBuilt"', () => {
@@ -1081,12 +928,14 @@ describe('BuildbotSyncer', () => {
                     'webkit': {'revision': 'WebKit'},
                     'shared': {'revision': 'Shared'},
                     'roots': {'roots': {}},
-                    'checkbox': {'ifBuilt': ['WebKit'], 'value': 'test-webkit'}
+                    'checkbox': {'ifBuilt': ['WebKit'], 'value': 'test-webkit'},
+                    'test-webkit': {'ifBuilt': ['WebKit'], 'value': true}
                 },
                 'buildProperties': {
                     'webkit': {'revision': 'WebKit'},
                     'webkit-patch': {'patch': 'WebKit'},
                     'checkbox': {'ifRepositorySet': ['WebKit'], 'value': 'build-webkit'},
+                    'build-webkit': {'ifRepositorySet': ['WebKit'], 'value': true},
                     'shared': {'revision': 'Shared'},
                 },
                 'acceptsRoots': true,
@@ -1098,6 +947,7 @@ describe('BuildbotSyncer', () => {
             assert.equal(properties['webkit'], '197463');
             assert.equal(properties['roots'], '[{"url":"http://build.webkit.org/api/uploaded-file/456.dat"}]');
             assert.equal(properties['checkbox'], 'test-webkit');
+            assert.equal(properties['test-webkit'], true);
         });
 
         it('should not set the value for "ifBuilt" if no build for the repository in the list appears', () => {
@@ -1109,13 +959,15 @@ describe('BuildbotSyncer', () => {
                     'webkit': {'revision': 'WebKit'},
                     'owner-repo': {'revision': 'Owner Repository'},
                     'roots': {'roots': {}},
-                    'checkbox': {'ifBuilt': ['WebKit'], 'value': 'test-webkit'}
+                    'checkbox': {'ifBuilt': ['WebKit'], 'value': 'test-webkit'},
+                    'test-webkit': {'ifBuilt': ['WebKit'], 'value': true}
                 },
                 'buildProperties': {
                     'webkit': {'revision': 'WebKit'},
                     'webkit-patch': {'patch': 'WebKit'},
                     'owner-repo': {'revision': 'Owner Repository'},
                     'checkbox': {'ifRepositorySet': ['WebKit'], 'value': 'build-webkit'},
+                    'build-webkit': {'ifRepositorySet': ['WebKit'], 'value': true},
                     'owned-commits': {'ownedRevisions': 'Owner Repository'}
                 },
                 'acceptsRoots': true,
@@ -1128,6 +980,7 @@ describe('BuildbotSyncer', () => {
             assert.equal(properties['webkit'], '197463');
             assert.equal(properties['roots'], '[{"url":"http://build.webkit.org/api/uploaded-file/456.dat"}]');
             assert.equal(properties['checkbox'], undefined);
+            assert.equal(properties['test-webkit'], undefined);
         });
 
         it('should resolve "ifRepositorySet" and "requiresBuild"', () => {
@@ -1145,6 +998,7 @@ describe('BuildbotSyncer', () => {
                     'webkit-patch': {'patch': 'WebKit'},
                     'owner-repo': {'revision': 'Owner Repository'},
                     'checkbox': {'ifRepositorySet': ['WebKit'], 'value': 'build-webkit'},
+                    'build-webkit': {'ifRepositorySet': ['WebKit'], 'value': true},
                     'owned-commits': {'ownedRevisions': 'Owner Repository'}
                 },
                 'acceptsRoots': true,
@@ -1155,6 +1009,7 @@ describe('BuildbotSyncer', () => {
             assert.equal(properties['webkit'], '197463');
             assert.equal(properties['owner-repo'], 'owner-001');
             assert.equal(properties['checkbox'], undefined);
+            assert.equal(properties['build-webkit'], undefined);
             assert.deepEqual(JSON.parse(properties['owned-commits']), {'Owner Repository': [{revision: 'owned-002', repository: 'Owned Repository', ownerRevision: 'owner-001'}]});
         });
 
@@ -1174,6 +1029,7 @@ describe('BuildbotSyncer', () => {
                     'webkit-patch': {'patch': 'WebKit'},
                     'owner-repo': {'revision': 'Owner Repository'},
                     'checkbox': {'ifRepositorySet': ['WebKit'], 'value': 'build-webkit'},
+                    'build-webkit': {'ifRepositorySet': ['WebKit'], 'value': true},
                     'owned-commits': {'ownedRevisions': 'Owner Repository'}
                 },
                 'acceptsRoots': true,
@@ -1184,6 +1040,7 @@ describe('BuildbotSyncer', () => {
             assert.equal(properties['webkit'], '197463');
             assert.equal(properties['owner-repo'], 'owner-001');
             assert.equal(properties['checkbox'], 'build-webkit');
+            assert.equal(properties['build-webkit'], true);
             assert.equal(properties['webkit-patch'], 'http://build.webkit.org/api/uploaded-file/453.dat');
             assert.deepEqual(JSON.parse(properties['owned-commits']), {'Owner Repository': [{revision: 'owned-002', repository: 'Owned Repository', ownerRevision: 'owner-001'}]});
         });
@@ -1196,12 +1053,152 @@ describe('BuildbotSyncer', () => {
         });
     });
 
+
+    describe('BuildbotBuildEntry', () => {
+        it('should create BuildbotBuildEntry for pending build', () => {
+            let syncer = BuildbotSyncer._loadConfig(MockRemoteAPI, sampleiOSConfig(), builderNameToIDMap())[1];
+            const buildbotData = samplePendingBuildRequests();
+            const pendingEntries = buildbotData.buildrequests.map((entry) => new BuildbotBuildEntry(syncer, entry));
+
+            assert.equal(pendingEntries.length, 1);
+            const entry = pendingEntries[0];
+            assert.ok(entry instanceof BuildbotBuildEntry);
+            assert.ok(!entry.buildNumber());
+            assert.ok(!entry.workerName());
+            assert.equal(entry.buildRequestId(), 16733);
+            assert.ok(entry.isPending());
+            assert.ok(!entry.isInProgress());
+            assert.ok(!entry.hasFinished());
+            assert.equal(entry.url(), 'http://build.webkit.org/#/buildrequests/17');
+        });
+
+        it('should create BuildbotBuildEntry for in-progress build', () => {
+            let syncer = BuildbotSyncer._loadConfig(MockRemoteAPI, sampleiOSConfig(), builderNameToIDMap())[1];
+            const buildbotData = sampleInProgressBuild();
+            const entries = buildbotData.builds.map((entry) => new BuildbotBuildEntry(syncer, entry));
+
+            assert.equal(entries.length, 1);
+            const entry = entries[0];
+            assert.ok(entry instanceof BuildbotBuildEntry);
+            assert.equal(entry.buildNumber(), 614);
+            assert.equal(entry.workerName(), 'ABTest-iPad-0');
+            assert.equal(entry.buildRequestId(), 16733);
+            assert.ok(!entry.isPending());
+            assert.ok(entry.isInProgress());
+            assert.ok(!entry.hasFinished());
+            assert.equal(entry.url(), 'http://build.webkit.org/#/builders/102/builds/614');
+        });
+
+        it('should create BuildbotBuildEntry for finished build', () => {
+            let syncer = BuildbotSyncer._loadConfig(MockRemoteAPI, sampleiOSConfig(), builderNameToIDMap())[1];
+            const buildbotData = sampleFinishedBuild();
+            const entries = buildbotData.builds.map((entry) => new BuildbotBuildEntry(syncer, entry));
+
+            assert.deepEqual(entries.length, 1);
+            const entry = entries[0];
+            assert.ok(entry instanceof BuildbotBuildEntry);
+            assert.equal(entry.buildNumber(), 1755);
+            assert.equal(entry.workerName(), 'ABTest-iPad-0');
+            assert.equal(entry.buildRequestId(), 18935);
+            assert.ok(!entry.isPending());
+            assert.ok(!entry.isInProgress());
+            assert.ok(entry.hasFinished());
+            assert.equal(entry.url(), 'http://build.webkit.org/#/builders/102/builds/1755');
+        });
+
+        it('should create BuildbotBuildEntry for mix of in-progress and finished builds', () => {
+            let syncer = BuildbotSyncer._loadConfig(MockRemoteAPI, sampleiOSConfig(), builderNameToIDMap())[1];
+            const buildbotData = {'builds': [sampleInProgressBuildData(), sampleFinishedBuildData()]};
+            const entries = buildbotData.builds.map((entry) => new BuildbotBuildEntry(syncer, entry));
+
+            assert.deepEqual(entries.length, 2);
+
+            let entry = entries[0];
+            assert.ok(entry instanceof BuildbotBuildEntry);
+            assert.equal(entry.buildNumber(), 614);
+            assert.equal(entry.workerName(), 'ABTest-iPad-0');
+            assert.equal(entry.buildRequestId(), 16733);
+            assert.ok(!entry.isPending());
+            assert.ok(entry.isInProgress());
+            assert.ok(!entry.hasFinished());
+            assert.equal(entry.url(), 'http://build.webkit.org/#/builders/102/builds/614');
+
+            entry = entries[1];
+            assert.ok(entry instanceof BuildbotBuildEntry);
+            assert.equal(entry.buildNumber(), 1755);
+            assert.equal(entry.slaveName(), 'ABTest-iPad-0');
+            assert.equal(entry.buildRequestId(), 18935);
+            assert.ok(!entry.isPending());
+            assert.ok(!entry.isInProgress());
+            assert.ok(entry.hasFinished());
+            assert.equal(entry.url(), 'http://build.webkit.org/#/builders/102/builds/1755');
+        });
+    });
+
+    describe('_pullRecentBuilds()', () => {
+        it('should not fetch recent builds when count is zero', async () => {
+            const syncer = BuildbotSyncer._loadConfig(MockRemoteAPI, sampleiOSConfig(), builderNameToIDMap())[1];
+            const promise = syncer._pullRecentBuilds(0);
+            assert.equal(requests.length, 0);
+            const content = await promise;
+            assert.deepEqual(content, []);
+        });
+
+        it('should pull the right number of recent builds', () => {
+            const syncer = BuildbotSyncer._loadConfig(MockRemoteAPI, sampleiOSConfig(), builderNameToIDMap())[1];
+            syncer._pullRecentBuilds(12);
+            assert.equal(requests.length, 1);
+            assert.equal(requests[0].url, '/api/v2/builders/102/builds?limit=12&order=-number&property=*');
+        });
+
+        it('should handle unexpected error while fetching recent builds', async () => {
+            const syncer = BuildbotSyncer._loadConfig(MockRemoteAPI, sampleiOSConfig(), builderNameToIDMap())[1];
+            const promise = syncer._pullRecentBuilds(2);
+            assert.equal(requests.length, 1);
+            assert.equal(requests[0].url, '/api/v2/builders/102/builds?limit=2&order=-number&property=*');
+            requests[0].resolve({'error': 'Unexpected error'});
+            const content = await promise;
+            assert.deepEqual(content, []);
+        });
+
+        it('should create BuildbotBuildEntry after fetching recent builds', async () => {
+            const syncer = BuildbotSyncer._loadConfig(MockRemoteAPI, sampleiOSConfig(), builderNameToIDMap())[1];
+            const promise = syncer._pullRecentBuilds(2);
+            assert.equal(requests.length, 1);
+            assert.equal(requests[0].url, '/api/v2/builders/102/builds?limit=2&order=-number&property=*');
+            requests[0].resolve({'builds': [sampleFinishedBuildData(), sampleInProgressBuildData()]});
+
+            const entries = await promise;
+            assert.deepEqual(entries.length, 2);
+
+            let entry = entries[0];
+            assert.ok(entry instanceof BuildbotBuildEntry);
+            assert.equal(entry.buildNumber(), 1755);
+            assert.equal(entry.workerName(), 'ABTest-iPad-0');
+            assert.equal(entry.buildRequestId(), 18935);
+            assert.ok(!entry.isPending());
+            assert.ok(!entry.isInProgress());
+            assert.ok(entry.hasFinished());
+            assert.equal(entry.url(), 'http://build.webkit.org/#/builders/102/builds/1755');
+
+            entry = entries[1];
+            assert.ok(entry instanceof BuildbotBuildEntry);
+            assert.equal(entry.buildNumber(), 614);
+            assert.equal(entry.slaveName(), 'ABTest-iPad-0');
+            assert.equal(entry.buildRequestId(), 16733);
+            assert.ok(!entry.isPending());
+            assert.ok(entry.isInProgress());
+            assert.ok(!entry.hasFinished());
+            assert.equal(entry.url(), 'http://build.webkit.org/#/builders/102/builds/614');
+        });
+    });
+
     describe('pullBuildbot', () => {
         it('should fetch pending builds from the right URL', () => {
             let syncer = BuildbotSyncer._loadConfig(MockRemoteAPI, sampleiOSConfig(), builderNameToIDMap())[1];
             assert.equal(syncer.builderName(), 'ABTest-iPad-RunBenchmark-Tests');
-            let expectedURL = '/json/builders/ABTest-iPad-RunBenchmark-Tests/pendingBuilds';
-            assert.equal(syncer.pathForPendingBuildsJSON(), expectedURL);
+            let expectedURL = '/api/v2/builders/102/buildrequests?complete=false&claimed=false&property=*';
+            assert.equal(syncer.pathForPendingBuilds(), expectedURL);
             syncer.pullBuildbot();
             assert.equal(requests.length, 1);
             assert.equal(requests[0].url, expectedURL);
@@ -1213,11 +1210,11 @@ describe('BuildbotSyncer', () => {
 
             syncer.pullBuildbot(1);
             assert.equal(requests.length, 1);
-            assert.equal(requests[0].url, '/json/builders/ABTest-iPad-RunBenchmark-Tests/pendingBuilds');
+            assert.equal(requests[0].url, '/api/v2/builders/102/buildrequests?complete=false&claimed=false&property=*');
             requests[0].resolve([]);
             return MockRemoteAPI.waitForRequest().then(() => {
                 assert.equal(requests.length, 2);
-                assert.equal(requests[1].url, '/json/builders/ABTest-iPad-RunBenchmark-Tests/builds/?select=-1');
+                assert.equal(requests[1].url, '/api/v2/builders/102/builds?limit=1&order=-number&property=*');
             });
         });
 
@@ -1226,18 +1223,18 @@ describe('BuildbotSyncer', () => {
 
             syncer.pullBuildbot(3);
             assert.equal(requests.length, 1);
-            assert.equal(requests[0].url, '/json/builders/ABTest-iPad-RunBenchmark-Tests/pendingBuilds');
+            assert.equal(requests[0].url, '/api/v2/builders/102/buildrequests?complete=false&claimed=false&property=*');
             requests[0].resolve([]);
             return MockRemoteAPI.waitForRequest().then(() => {
                 assert.equal(requests.length, 2);
-                assert.equal(requests[1].url, '/json/builders/ABTest-iPad-RunBenchmark-Tests/builds/?select=-1&select=-2&select=-3');
+                assert.equal(requests[1].url, '/api/v2/builders/102/builds?limit=3&order=-number&property=*');
             });
         });
 
         it('should create BuildbotBuildEntry for pending builds', () => {
             let syncer = BuildbotSyncer._loadConfig(MockRemoteAPI, sampleiOSConfig(), builderNameToIDMap())[1];
             let promise = syncer.pullBuildbot();
-            requests[0].resolve([samplePendingBuild()]);
+            requests[0].resolve(samplePendingBuildRequests());
             return promise.then((entries) => {
                 assert.equal(entries.length, 1);
                 let entry = entries[0];
@@ -1248,7 +1245,7 @@ describe('BuildbotSyncer', () => {
                 assert.ok(entry.isPending());
                 assert.ok(!entry.isInProgress());
                 assert.ok(!entry.hasFinished());
-                assert.equal(entry.url(), 'http://build.webkit.org/builders/ABTest-iPad-RunBenchmark-Tests/');
+                assert.equal(entry.url(), 'http://build.webkit.org/#/buildrequests/17');
             });
         });
 
@@ -1260,7 +1257,7 @@ describe('BuildbotSyncer', () => {
             requests[0].resolve([]);
             return MockRemoteAPI.waitForRequest().then(() => {
                 assert.equal(requests.length, 2);
-                requests[1].resolve({[-1]: sampleInProgressBuild()});
+                requests[1].resolve(sampleInProgressBuild());
                 return promise;
             }).then((entries) => {
                 assert.equal(entries.length, 1);
@@ -1272,7 +1269,7 @@ describe('BuildbotSyncer', () => {
                 assert.ok(!entry.isPending());
                 assert.ok(entry.isInProgress());
                 assert.ok(!entry.hasFinished());
-                assert.equal(entry.url(), 'http://build.webkit.org/builders/ABTest-iPad-RunBenchmark-Tests/builds/614');
+                assert.equal(entry.url(), 'http://build.webkit.org/#/builders/102/builds/614');
             });
         });
 
@@ -1284,7 +1281,7 @@ describe('BuildbotSyncer', () => {
             requests[0].resolve([]);
             return MockRemoteAPI.waitForRequest().then(() => {
                 assert.equal(requests.length, 2);
-                requests[1].resolve({[-1]: sampleFinishedBuild()});
+                requests[1].resolve(sampleFinishedBuild());
                 return promise;
             }).then((entries) => {
                 assert.deepEqual(entries.length, 1);
@@ -1296,7 +1293,7 @@ describe('BuildbotSyncer', () => {
                 assert.ok(!entry.isPending());
                 assert.ok(!entry.isInProgress());
                 assert.ok(entry.hasFinished());
-                assert.equal(entry.url(), 'http://build.webkit.org/builders/ABTest-iPad-RunBenchmark-Tests/builds/1755');
+                assert.equal(entry.url(), 'http://build.webkit.org/#/builders/102/builds/1755');
             });
         });
 
@@ -1306,11 +1303,11 @@ describe('BuildbotSyncer', () => {
             let promise = syncer.pullBuildbot(5);
             assert.equal(requests.length, 1);
 
-            requests[0].resolve([samplePendingBuild(123)]);
+            requests[0].resolve(samplePendingBuildRequests(123));
 
             return MockRemoteAPI.waitForRequest().then(() => {
                 assert.equal(requests.length, 2);
-                requests[1].resolve({[-1]: sampleFinishedBuild(), [-2]: {'error': 'Not available'}, [-4]: sampleInProgressBuild()});
+                requests[1].resolve({'builds': [sampleFinishedBuildData(), sampleInProgressBuildData()]});
                 return promise;
             }).then((entries) => {
                 assert.deepEqual(entries.length, 3);
@@ -1323,7 +1320,7 @@ describe('BuildbotSyncer', () => {
                 assert.ok(entry.isPending());
                 assert.ok(!entry.isInProgress());
                 assert.ok(!entry.hasFinished());
-                assert.equal(entry.url(), 'http://build.webkit.org/builders/ABTest-iPad-RunBenchmark-Tests/');
+                assert.equal(entry.url(), 'http://build.webkit.org/#/buildrequests/17');
 
                 entry = entries[1];
                 assert.ok(entry instanceof BuildbotBuildEntry);
@@ -1333,7 +1330,7 @@ describe('BuildbotSyncer', () => {
                 assert.ok(!entry.isPending());
                 assert.ok(entry.isInProgress());
                 assert.ok(!entry.hasFinished());
-                assert.equal(entry.url(), 'http://build.webkit.org/builders/ABTest-iPad-RunBenchmark-Tests/builds/614');
+                assert.equal(entry.url(), 'http://build.webkit.org/#/builders/102/builds/614');
 
                 entry = entries[2];
                 assert.ok(entry instanceof BuildbotBuildEntry);
@@ -1343,7 +1340,7 @@ describe('BuildbotSyncer', () => {
                 assert.ok(!entry.isPending());
                 assert.ok(!entry.isInProgress());
                 assert.ok(entry.hasFinished());
-                assert.equal(entry.url(), 'http://build.webkit.org/builders/ABTest-iPad-RunBenchmark-Tests/builds/1755');
+                assert.equal(entry.url(), 'http://build.webkit.org/#/builders/102/builds/1755');
             });
         });
 
@@ -1353,11 +1350,11 @@ describe('BuildbotSyncer', () => {
             let promise = syncer.pullBuildbot(5);
             assert.equal(requests.length, 1);
 
-            requests[0].resolve([samplePendingBuild(456, 2), samplePendingBuild(123, 1)]);
+            requests[0].resolve({"buildrequests": [samplePendingBuildRequestData(456, 2), samplePendingBuildRequestData(123, 1)]});
 
             return MockRemoteAPI.waitForRequest().then(() => {
                 assert.equal(requests.length, 2);
-                requests[1].resolve({[-3]: sampleFinishedBuild(), [-1]: {'error': 'Not available'}, [-2]: sampleInProgressBuild()});
+                requests[1].resolve({'builds': [sampleFinishedBuildData(), sampleInProgressBuildData()]});
                 return promise;
             }).then((entries) => {
                 assert.deepEqual(entries.length, 4);
@@ -1370,7 +1367,7 @@ describe('BuildbotSyncer', () => {
                 assert.ok(entry.isPending());
                 assert.ok(!entry.isInProgress());
                 assert.ok(!entry.hasFinished());
-                assert.equal(entry.url(), 'http://build.webkit.org/builders/ABTest-iPad-RunBenchmark-Tests/');
+                assert.equal(entry.url(), 'http://build.webkit.org/#/buildrequests/17');
 
                 entry = entries[1];
                 assert.ok(entry instanceof BuildbotBuildEntry);
@@ -1380,7 +1377,7 @@ describe('BuildbotSyncer', () => {
                 assert.ok(entry.isPending());
                 assert.ok(!entry.isInProgress());
                 assert.ok(!entry.hasFinished());
-                assert.equal(entry.url(), 'http://build.webkit.org/builders/ABTest-iPad-RunBenchmark-Tests/');
+                assert.equal(entry.url(), 'http://build.webkit.org/#/buildrequests/17');
 
                 entry = entries[2];
                 assert.ok(entry instanceof BuildbotBuildEntry);
@@ -1390,7 +1387,7 @@ describe('BuildbotSyncer', () => {
                 assert.ok(!entry.isPending());
                 assert.ok(entry.isInProgress());
                 assert.ok(!entry.hasFinished());
-                assert.equal(entry.url(), 'http://build.webkit.org/builders/ABTest-iPad-RunBenchmark-Tests/builds/614');
+                assert.equal(entry.url(), 'http://build.webkit.org/#/builders/102/builds/614');
 
                 entry = entries[3];
                 assert.ok(entry instanceof BuildbotBuildEntry);
@@ -1400,7 +1397,7 @@ describe('BuildbotSyncer', () => {
                 assert.ok(!entry.isPending());
                 assert.ok(!entry.isInProgress());
                 assert.ok(entry.hasFinished());
-                assert.equal(entry.url(), 'http://build.webkit.org/builders/ABTest-iPad-RunBenchmark-Tests/builds/1755');
+                assert.equal(entry.url(), 'http://build.webkit.org/#/builders/102/builds/1755');
             });
         });
 
@@ -1410,11 +1407,11 @@ describe('BuildbotSyncer', () => {
             let promise = syncer.pullBuildbot(5);
             assert.equal(requests.length, 1);
 
-            requests[0].resolve([samplePendingBuild()]);
+            requests[0].resolve(samplePendingBuildRequests());
 
             return MockRemoteAPI.waitForRequest().then(() => {
                 assert.equal(requests.length, 2);
-                requests[1].resolve({[-1]: sampleInProgressBuild()});
+                requests[1].resolve(sampleInProgressBuild());
                 return promise;
             }).then((entries) => {
                 assert.equal(entries.length, 1);
@@ -1427,7 +1424,7 @@ describe('BuildbotSyncer', () => {
                 assert.ok(!entry.isPending());
                 assert.ok(entry.isInProgress());
                 assert.ok(!entry.hasFinished());
-                assert.equal(entry.url(), 'http://build.webkit.org/builders/ABTest-iPad-RunBenchmark-Tests/builds/614');
+                assert.equal(entry.url(), 'http://build.webkit.org/#/builders/102/builds/614');
             });
         });
 
@@ -1437,11 +1434,11 @@ describe('BuildbotSyncer', () => {
             let promise = syncer.pullBuildbot(5);
             assert.equal(requests.length, 1);
 
-            requests[0].resolve([samplePendingBuild()]);
+            requests[0].resolve(samplePendingBuildRequests());
 
             return MockRemoteAPI.waitForRequest().then(() => {
                 assert.equal(requests.length, 2);
-                requests[1].resolve({[-1]: sampleFinishedBuild(16733)});
+                requests[1].resolve(sampleFinishedBuild(16733));
                 return promise;
             }).then((entries) => {
                 assert.equal(entries.length, 1);
@@ -1454,7 +1451,34 @@ describe('BuildbotSyncer', () => {
                 assert.ok(!entry.isPending());
                 assert.ok(!entry.isInProgress());
                 assert.ok(entry.hasFinished());
-                assert.equal(entry.url(), 'http://build.webkit.org/builders/ABTest-iPad-RunBenchmark-Tests/builds/1755');
+                assert.equal(entry.url(), 'http://build.webkit.org/#/builders/102/builds/1755');
+            });
+        });
+    });
+
+    describe('scheduleBuildOnBuildbot', () => {
+        it('should schedule a build request on Buildbot', async () => {
+            const syncer = BuildbotSyncer._loadConfig(MockRemoteAPI, sampleiOSConfig(), builderNameToIDMap())[0];
+            const request = createSampleBuildRequest(MockModels.iphone, MockModels.speedometer);
+            const properties = syncer._propertiesForBuildRequest(request, [request]);
+            const promise  = syncer.scheduleBuildOnBuildbot(properties);
+
+            assert.equal(requests.length, 1);
+            assert.equal(requests[0].method, 'POST');
+            assert.equal(requests[0].url, '/api/v2/forceschedulers/ABTest-iPhone-RunBenchmark-Tests-ForceScheduler');
+            requests[0].resolve();
+            await promise;
+            assert.deepEqual(requests[0].data, {
+                'id': '16733-' + MockModels.iphone.id(),
+                'jsonrpc': '2.0',
+                'method': 'force',
+                'params': {
+                    'build_request_id': '16733-' + MockModels.iphone.id(),
+                    'desired_image': '13A452',
+                    'opensource': '197463',
+                    'forcescheduler': 'ABTest-iPhone-RunBenchmark-Tests-ForceScheduler',
+                    'test_name': 'speedometer'
+                }
             });
         });
     });
@@ -1468,15 +1492,20 @@ describe('BuildbotSyncer', () => {
             syncer.scheduleRequest(request, [request], 'some-slave');
             return waitForRequest.then(() => {
                 assert.equal(requests.length, 1);
-                assert.equal(requests[0].url, '/builders/ABTest-iPhone-RunBenchmark-Tests/force');
+                assert.equal(requests[0].url, '/api/v2/forceschedulers/ABTest-iPhone-RunBenchmark-Tests-ForceScheduler');
                 assert.equal(requests[0].method, 'POST');
                 assert.deepEqual(requests[0].data, {
-                    'build_request_id': '16733-' + MockModels.iphone.id(),
-                    'desired_image': '13A452',
-                    "opensource": "197463",
-                    'forcescheduler': 'ABTest-iPhone-RunBenchmark-Tests-ForceScheduler',
-                    'slavename': 'some-slave',
-                    'test_name': 'speedometer'
+                    'id': '16733-' + MockModels.iphone.id(),
+                    'jsonrpc': '2.0',
+                    'method': 'force',
+                    'params': {
+                        'build_request_id': '16733-' + MockModels.iphone.id(),
+                        'desired_image': '13A452',
+                        'opensource': '197463',
+                        'forcescheduler': 'ABTest-iPhone-RunBenchmark-Tests-ForceScheduler',
+                        'slavename': 'some-slave',
+                        'test_name': 'speedometer'
+                    }
                 });
             });
         });
@@ -1500,33 +1529,35 @@ describe('BuildbotSyncer', () => {
         it('should schedule a build if builder has no builds if slaveList is not specified', () => {
             let syncer = BuildbotSyncer._loadConfig(MockRemoteAPI, smallConfiguration(), builderNameToIDMap())[0];
 
-            return pullBuildbotWithAssertion(syncer, [], {}).then(() => {
+            return pullBuildbotWithAssertion(syncer, {}, {}).then(() => {
                 const request = createSampleBuildRequest(MockModels.somePlatform, MockModels.someTest);
                 syncer.scheduleRequestInGroupIfAvailable(request, [request]);
                 assert.equal(requests.length, 1);
-                assert.equal(requests[0].url, '/builders/some%20builder/force');
+                assert.equal(requests[0].url, '/api/v2/forceschedulers/some-builder-ForceScheduler');
                 assert.equal(requests[0].method, 'POST');
-                assert.deepEqual(requests[0].data, {id: '16733-' + MockModels.somePlatform.id(), 'os': '13A452', 'wk': '197463'});
+                assert.deepEqual(requests[0].data, {id: '16733-' + MockModels.somePlatform.id(), 'jsonrpc': '2.0', 'method': 'force',
+                    'params': {id: '16733-' + MockModels.somePlatform.id(), 'forcescheduler': 'some-builder-ForceScheduler', 'os': '13A452', 'wk': '197463'}});
             });
         });
 
         it('should schedule a build if builder only has finished builds if slaveList is not specified', () => {
             let syncer = BuildbotSyncer._loadConfig(MockRemoteAPI, smallConfiguration(), builderNameToIDMap())[0];
 
-            return pullBuildbotWithAssertion(syncer, [], {[-1]: smallFinishedBuild()}).then(() => {
+            return pullBuildbotWithAssertion(syncer, {}, smallFinishedBuild()).then(() => {
                 const request = createSampleBuildRequest(MockModels.somePlatform, MockModels.someTest);
                 syncer.scheduleRequestInGroupIfAvailable(request, [request]);
                 assert.equal(requests.length, 1);
-                assert.equal(requests[0].url, '/builders/some%20builder/force');
+                assert.equal(requests[0].url, '/api/v2/forceschedulers/some-builder-ForceScheduler');
                 assert.equal(requests[0].method, 'POST');
-                assert.deepEqual(requests[0].data, {id: '16733-' + MockModels.somePlatform.id(), 'os': '13A452', 'wk': '197463'});
+                assert.deepEqual(requests[0].data, {id: '16733-' + MockModels.somePlatform.id(), 'jsonrpc': '2.0', 'method': 'force',
+                    'params': {id: '16733-' + MockModels.somePlatform.id(), 'forcescheduler': 'some-builder-ForceScheduler', 'os': '13A452', 'wk': '197463'}});
             });
         });
 
         it('should not schedule a build if builder has a pending build if slaveList is not specified', () => {
             let syncer = BuildbotSyncer._loadConfig(MockRemoteAPI, smallConfiguration(), builderNameToIDMap())[0];
 
-            return pullBuildbotWithAssertion(syncer, [smallPendingBuild()], {}).then(() => {
+            return pullBuildbotWithAssertion(syncer, smallPendingBuild(), {}).then(() => {
                 syncer.scheduleRequestInGroupIfAvailable(createSampleBuildRequest(MockModels.somePlatform, MockModels.someTest));
                 assert.equal(requests.length, 0);
             });
@@ -1535,11 +1566,11 @@ describe('BuildbotSyncer', () => {
         it('should schedule a build if builder does not have pending or completed builds on the matching slave', () => {
             let syncer = BuildbotSyncer._loadConfig(MockRemoteAPI, sampleiOSConfig(), builderNameToIDMap())[0];
 
-            return pullBuildbotWithAssertion(syncer, [], {}).then(() => {
+            return pullBuildbotWithAssertion(syncer, {}, {}).then(() => {
                 const request = createSampleBuildRequest(MockModels.iphone, MockModels.speedometer);
                 syncer.scheduleRequestInGroupIfAvailable(request, [request], null);
                 assert.equal(requests.length, 1);
-                assert.equal(requests[0].url, '/builders/ABTest-iPhone-RunBenchmark-Tests/force');
+                assert.equal(requests[0].url, '/api/v2/forceschedulers/ABTest-iPhone-RunBenchmark-Tests-ForceScheduler');
                 assert.equal(requests[0].method, 'POST');
             });
         });
@@ -1547,11 +1578,11 @@ describe('BuildbotSyncer', () => {
         it('should schedule a build if builder only has finished builds on the matching slave', () => {
             let syncer = BuildbotSyncer._loadConfig(MockRemoteAPI, sampleiOSConfig(), builderNameToIDMap())[1];
 
-            pullBuildbotWithAssertion(syncer, [], {[-1]: sampleFinishedBuild()}).then(() => {
+            pullBuildbotWithAssertion(syncer, {}, sampleFinishedBuild()).then(() => {
                 const request = createSampleBuildRequest(MockModels.ipad, MockModels.speedometer);
                 syncer.scheduleRequestInGroupIfAvailable(request, [request], null);
                 assert.equal(requests.length, 1);
-                assert.equal(requests[0].url, '/builders/ABTest-iPad-RunBenchmark-Tests/force');
+                assert.equal(requests[0].url, '/api/v2/forceschedulers/ABTest-iPad-RunBenchmark-Tests-ForceScheduler');
                 assert.equal(requests[0].method, 'POST');
             });
         });
@@ -1559,7 +1590,7 @@ describe('BuildbotSyncer', () => {
         it('should not schedule a build if builder has a pending build on the maching slave', () => {
             let syncer = BuildbotSyncer._loadConfig(MockRemoteAPI, sampleiOSConfig(), builderNameToIDMap())[1];
 
-            pullBuildbotWithAssertion(syncer, [samplePendingBuild()], {}).then(() => {
+            pullBuildbotWithAssertion(syncer, samplePendingBuildRequests(), {}).then(() => {
                 const request = createSampleBuildRequest(MockModels.ipad, MockModels.speedometer);
                 syncer.scheduleRequestInGroupIfAvailable(request, [request], null);
                 assert.equal(requests.length, 0);
@@ -1569,7 +1600,7 @@ describe('BuildbotSyncer', () => {
         it('should schedule a build if builder only has a pending build on a non-maching slave', () => {
             let syncer = BuildbotSyncer._loadConfig(MockRemoteAPI, sampleiOSConfig(), builderNameToIDMap())[1];
 
-            return pullBuildbotWithAssertion(syncer, [samplePendingBuild(1, 1, 'another-slave')], {}).then(() => {
+            return pullBuildbotWithAssertion(syncer, samplePendingBuildRequests(1, 1, 'another-slave'), {}).then(() => {
                 const request = createSampleBuildRequest(MockModels.ipad, MockModels.speedometer);
                 syncer.scheduleRequestInGroupIfAvailable(request, [request], null);
                 assert.equal(requests.length, 1);
@@ -1579,7 +1610,7 @@ describe('BuildbotSyncer', () => {
         it('should schedule a build if builder only has an in-progress build on the matching slave', () => {
             let syncer = BuildbotSyncer._loadConfig(MockRemoteAPI, sampleiOSConfig(), builderNameToIDMap())[1];
 
-            return pullBuildbotWithAssertion(syncer, [], {[-1]: sampleInProgressBuild()}).then(() => {
+            return pullBuildbotWithAssertion(syncer, {}, sampleInProgressBuild()).then(() => {
                 const request = createSampleBuildRequest(MockModels.ipad, MockModels.speedometer);
                 syncer.scheduleRequestInGroupIfAvailable(request, [request], null);
                 assert.equal(requests.length, 1);
@@ -1589,7 +1620,7 @@ describe('BuildbotSyncer', () => {
         it('should schedule a build if builder has an in-progress build on another slave', () => {
             let syncer = BuildbotSyncer._loadConfig(MockRemoteAPI, sampleiOSConfig(), builderNameToIDMap())[1];
 
-            return pullBuildbotWithAssertion(syncer, [], {[-1]: sampleInProgressBuild('other-slave')}).then(() => {
+            return pullBuildbotWithAssertion(syncer, {}, sampleInProgressBuild('other-slave')).then(() => {
                 const request = createSampleBuildRequest(MockModels.ipad, MockModels.speedometer);
                 syncer.scheduleRequestInGroupIfAvailable(request, [request], null);
                 assert.equal(requests.length, 1);
@@ -1599,7 +1630,7 @@ describe('BuildbotSyncer', () => {
         it('should not schedule a build if the request does not match any configuration', () => {
             let syncer = BuildbotSyncer._loadConfig(MockRemoteAPI, sampleiOSConfig(), builderNameToIDMap())[0];
 
-            return pullBuildbotWithAssertion(syncer, [], {}).then(() => {
+            return pullBuildbotWithAssertion(syncer, {}, {}).then(() => {
                 const request = createSampleBuildRequest(MockModels.ipad, MockModels.speedometer);
                 syncer.scheduleRequestInGroupIfAvailable(request, [request], null);
                 assert.equal(requests.length, 0);
@@ -1609,7 +1640,7 @@ describe('BuildbotSyncer', () => {
         it('should not schedule a build if a new request had been submitted to the same slave', (done) => {
             let syncer = BuildbotSyncer._loadConfig(MockRemoteAPI, sampleiOSConfig(), builderNameToIDMap())[1];
 
-            pullBuildbotWithAssertion(syncer, [], {}).then(() => {
+            pullBuildbotWithAssertion(syncer, {}, {}).then(() => {
                 let request = createSampleBuildRequest(MockModels.ipad, MockModels.speedometer);
                 syncer.scheduleRequest(request, [request], 'ABTest-iPad-0');
                 request = createSampleBuildRequest(MockModels.ipad, MockModels.speedometer);
@@ -1627,7 +1658,7 @@ describe('BuildbotSyncer', () => {
         it('should schedule a build if a new request had been submitted to another slave', () => {
             let syncer = BuildbotSyncer._loadConfig(MockRemoteAPI, sampleiOSConfig(), builderNameToIDMap())[1];
 
-            return pullBuildbotWithAssertion(syncer, [], {}).then(() => {
+            return pullBuildbotWithAssertion(syncer, {}, {}).then(() => {
                 let request = createSampleBuildRequest(MockModels.ipad, MockModels.speedometer);
                 syncer.scheduleRequest(request, [request], 'ABTest-iPad-0');
                 assert.equal(requests.length, 1);
@@ -1640,7 +1671,7 @@ describe('BuildbotSyncer', () => {
         it('should not schedule a build if a new request had been submitted to the same builder without slaveList', () => {
             let syncer = BuildbotSyncer._loadConfig(MockRemoteAPI, smallConfiguration(), builderNameToIDMap())[0];
 
-            return pullBuildbotWithAssertion(syncer, [], {}).then(() => {
+            return pullBuildbotWithAssertion(syncer, {}, {}).then(() => {
                 let request = createSampleBuildRequest(MockModels.somePlatform, MockModels.someTest);
                 syncer.scheduleRequest(request, [request], null);
                 assert.equal(requests.length, 1);