Update test cases for change r206465.
[WebKit.git] / Websites / perf.webkit.org / server-tests / tools-buildbot-triggerable-tests.js
1 'use strict';
2
3 const assert = require('assert');
4
5 const BuildbotTriggerable = require('../tools/js/buildbot-triggerable.js').BuildbotTriggerable;
6 const MockData = require('./resources/mock-data.js');
7 const MockRemoteAPI = require('../unit-tests/resources/mock-remote-api.js').MockRemoteAPI;
8 const TestServer = require('./resources/test-server.js');
9 const connectToDatabaseInEveryTest = require('./resources/common-operations.js').connectToDatabaseInEveryTest;
10
11 class MockLogger {
12     constructor()
13     {
14         this._logs = [];
15     }
16
17     log(text) { this._logs.push(text); }
18     error(text) { this._logs.push(text); }
19 }
20
21 describe('BuildbotTriggerable', function () {
22     this.timeout(1000);
23     TestServer.inject();
24
25     beforeEach(function () {
26         MockData.resetV3Models();
27         MockRemoteAPI.reset('http://build.webkit.org');
28     });
29
30     describe('syncOnce', function () {
31         it('should schedule the next build request when there are no pending builds', function (done) {
32             let db = TestServer.database();
33             let syncPromise;
34             db.connect().then(function () {
35                 return MockData.addMockData(db, ['completed', 'running', 'pending', 'pending']);
36             }).then(function () {
37                 return Manifest.fetch();
38             }).then(function () {
39                 let config = MockData.mockTestSyncConfigWithSingleBuilder();
40                 let logger = new MockLogger;
41                 let slaveInfo = {name: 'sync-slave', password: 'password'};
42                 let triggerable = new BuildbotTriggerable(config, TestServer.remoteAPI(), MockRemoteAPI, slaveInfo, logger);
43                 syncPromise = triggerable.syncOnce();
44                 syncPromise.catch(done);
45                 return MockRemoteAPI.waitForRequest();
46             }).then(function () {
47                 assert.equal(BuildRequest.all().length, 4);
48                 assert.equal(BuildRequest.findById(700).status(), 'completed');
49                 assert.equal(BuildRequest.findById(701).status(), 'running');
50                 assert.equal(BuildRequest.findById(702).status(), 'pending');
51                 assert.equal(BuildRequest.findById(703).status(), 'pending');
52                 assert.equal(MockRemoteAPI.requests[0].method, 'GET');
53                 assert.equal(MockRemoteAPI.requests[0].url, '/json/builders/some-builder-1/pendingBuilds');
54                 MockRemoteAPI.requests[0].resolve([]);
55                 return MockRemoteAPI.waitForRequest();
56             }).then(function () {
57                 assert.equal(MockRemoteAPI.requests[1].method, 'GET');
58                 assert.equal(MockRemoteAPI.requests[1].url, '/json/builders/some-builder-1/builds/?select=-1&select=-2');
59                 MockRemoteAPI.requests[1].resolve({[-1]: MockData.runningBuild(), [-2]: MockData.finishedBuild()});
60                 return MockRemoteAPI.waitForRequest();
61             }).then(function () {
62                 assert.equal(MockRemoteAPI.requests[2].method, 'POST');
63                 assert.equal(MockRemoteAPI.requests[2].url, '/builders/some-builder-1/force');
64                 assert.deepEqual(MockRemoteAPI.requests[2].data, {'wk': '191622', 'os': '10.11 15A284', 'build-request-id': '702'});
65                 MockRemoteAPI.requests[2].resolve('OK');
66                 return MockRemoteAPI.waitForRequest();
67             }).then(function () {
68                 assert.equal(MockRemoteAPI.requests[3].method, 'GET');
69                 assert.equal(MockRemoteAPI.requests[3].url, '/json/builders/some-builder-1/pendingBuilds');
70                 MockRemoteAPI.requests[3].resolve([MockData.pendingBuild()])
71                 return MockRemoteAPI.waitForRequest();
72             }).then(function () {
73                 assert.equal(MockRemoteAPI.requests[4].method, 'GET');
74                 assert.equal(MockRemoteAPI.requests[4].url, '/json/builders/some-builder-1/builds/?select=-1&select=-2');
75                 MockRemoteAPI.requests[4].resolve({[-1]: MockData.runningBuild(), [-2]: MockData.finishedBuild()});
76                 return syncPromise;
77             }).then(function () {
78                 return BuildRequest.fetchForTriggerable(MockData.mockTestSyncConfigWithSingleBuilder().triggerableName);
79             }).then(function () {
80                 assert.equal(BuildRequest.all().length, 4);
81                 assert.equal(BuildRequest.findById(700).status(), 'completed');
82                 assert.equal(BuildRequest.findById(701).status(), 'running');
83                 assert.equal(BuildRequest.findById(702).status(), 'scheduled');
84                 assert.equal(BuildRequest.findById(703).status(), 'pending');
85                 done();
86             }).catch(done);
87         });
88
89         it('should not schedule the next build request when there is a pending build', function (done) {
90             let db = TestServer.database();
91             let syncPromise;
92             db.connect().then(function () {
93                 return MockData.addMockData(db, ['completed', 'running', 'pending', 'pending']);
94             }).then(function () {
95                 return Manifest.fetch();
96             }).then(function () {
97                 let config = MockData.mockTestSyncConfigWithSingleBuilder();
98                 let logger = new MockLogger;
99                 let slaveInfo = {name: 'sync-slave', password: 'password'};
100                 let triggerable = new BuildbotTriggerable(config, TestServer.remoteAPI(), MockRemoteAPI, slaveInfo, logger);
101                 syncPromise = triggerable.syncOnce();
102                 syncPromise.catch(done);
103                 return MockRemoteAPI.waitForRequest();
104             }).then(function () {
105                 assert.equal(MockRemoteAPI.requests[0].method, 'GET');
106                 assert.equal(MockRemoteAPI.requests[0].url, '/json/builders/some-builder-1/pendingBuilds');
107                 MockRemoteAPI.requests[0].resolve([MockData.pendingBuild()]);
108                 return MockRemoteAPI.waitForRequest();
109             }).then(function () {
110                 assert.equal(MockRemoteAPI.requests[1].method, 'GET');
111                 assert.equal(MockRemoteAPI.requests[1].url, '/json/builders/some-builder-1/builds/?select=-1&select=-2');
112                 MockRemoteAPI.requests[1].resolve({[-1]: MockData.runningBuild(), [-2]: MockData.finishedBuild()});
113                 return MockRemoteAPI.waitForRequest();
114             }).then(function () {
115                 assert.equal(MockRemoteAPI.requests[2].method, 'GET');
116                 assert.equal(MockRemoteAPI.requests[2].url, '/json/builders/some-builder-1/pendingBuilds');
117                 MockRemoteAPI.requests[2].resolve([MockData.pendingBuild()])
118                 return MockRemoteAPI.waitForRequest();
119             }).then(function () {
120                 assert.equal(MockRemoteAPI.requests[3].method, 'GET');
121                 assert.equal(MockRemoteAPI.requests[3].url, '/json/builders/some-builder-1/builds/?select=-1&select=-2');
122                 MockRemoteAPI.requests[3].resolve({[-1]: MockData.runningBuild(), [-2]: MockData.finishedBuild()});
123                 return syncPromise;
124             }).then(function () {
125                 assert.equal(BuildRequest.all().length, 4);
126                 assert.equal(BuildRequest.findById(700).status(), 'completed');
127                 assert.equal(BuildRequest.findById(701).status(), 'running');
128                 assert.equal(BuildRequest.findById(702).status(), 'pending');
129                 assert.equal(BuildRequest.findById(703).status(), 'pending');
130                 return BuildRequest.fetchForTriggerable(MockData.mockTestSyncConfigWithSingleBuilder().triggerableName);
131             }).then(function () {
132                 assert.equal(BuildRequest.all().length, 4);
133                 assert.equal(BuildRequest.findById(700).status(), 'completed');
134                 assert.equal(BuildRequest.findById(701).status(), 'running');
135                 assert.equal(BuildRequest.findById(702).status(), 'scheduled');
136                 assert.equal(BuildRequest.findById(703).status(), 'pending');
137                 done();
138             }).catch(done);
139         });
140
141         it('should schedule the build request on a builder without a pending build if it\'s the first request in the group', function (done) {
142             let db = TestServer.database();
143             let syncPromise;
144             db.connect().then(function () {
145                 return MockData.addMockData(db, ['pending', 'pending', 'pending', 'pending']);
146             }).then(function () {
147                 return Manifest.fetch();
148             }).then(function () {
149                 let config = MockData.mockTestSyncConfigWithTwoBuilders();
150                 let logger = new MockLogger;
151                 let slaveInfo = {name: 'sync-slave', password: 'password'};
152                 let triggerable = new BuildbotTriggerable(config, TestServer.remoteAPI(), MockRemoteAPI, slaveInfo, logger);
153                 syncPromise = triggerable.syncOnce();
154                 syncPromise.catch(done);
155                 return MockRemoteAPI.waitForRequest();
156             }).then(function () {
157                 assert.equal(MockRemoteAPI.requests.length, 2);
158                 assert.equal(MockRemoteAPI.requests[0].method, 'GET');
159                 assert.equal(MockRemoteAPI.requests[0].url, '/json/builders/some-builder-1/pendingBuilds');
160                 MockRemoteAPI.requests[0].resolve([MockData.pendingBuild({buildRequestId: 999})]);
161                 assert.equal(MockRemoteAPI.requests[1].method, 'GET');
162                 assert.equal(MockRemoteAPI.requests[1].url, '/json/builders/some%20builder%202/pendingBuilds');
163                 MockRemoteAPI.requests[1].resolve([]);
164                 return MockRemoteAPI.waitForRequest();
165             }).then(function () {
166                 assert.equal(MockRemoteAPI.requests.length, 4);
167                 assert.equal(MockRemoteAPI.requests[2].method, 'GET');
168                 assert.equal(MockRemoteAPI.requests[2].url, '/json/builders/some-builder-1/builds/?select=-1&select=-2');
169                 MockRemoteAPI.requests[2].resolve({});
170                 assert.equal(MockRemoteAPI.requests[3].method, 'GET');
171                 assert.equal(MockRemoteAPI.requests[3].url, '/json/builders/some%20builder%202/builds/?select=-1&select=-2');
172                 MockRemoteAPI.requests[3].resolve({});
173                 return MockRemoteAPI.waitForRequest();
174             }).then(function () {
175                 assert.equal(MockRemoteAPI.requests.length, 5);
176                 assert.equal(MockRemoteAPI.requests[4].method, 'POST');
177                 assert.equal(MockRemoteAPI.requests[4].url, '/builders/some%20builder%202/force');
178                 assert.deepEqual(MockRemoteAPI.requests[4].data, {'wk': '191622', 'os': '10.11 15A284', 'build-request-id': '700'});
179                 MockRemoteAPI.requests[4].resolve('OK');
180                 return MockRemoteAPI.waitForRequest();
181             }).then(function () {
182                 assert.equal(MockRemoteAPI.requests.length, 7);
183                 assert.equal(MockRemoteAPI.requests[5].method, 'GET');
184                 assert.equal(MockRemoteAPI.requests[5].url, '/json/builders/some-builder-1/pendingBuilds');
185                 MockRemoteAPI.requests[5].resolve([MockData.pendingBuild({buildRequestId: 999})]);
186                 assert.equal(MockRemoteAPI.requests[6].method, 'GET');
187                 assert.equal(MockRemoteAPI.requests[6].url, '/json/builders/some%20builder%202/pendingBuilds');
188                 MockRemoteAPI.requests[6].resolve([MockData.pendingBuild({builder: 'some builder 2', buildRequestId: 700})]);
189                 return MockRemoteAPI.waitForRequest();
190             }).then(function () {
191                 assert.equal(MockRemoteAPI.requests.length, 9);
192                 assert.equal(MockRemoteAPI.requests[7].method, 'GET');
193                 assert.equal(MockRemoteAPI.requests[7].url, '/json/builders/some-builder-1/builds/?select=-1&select=-2');
194                 MockRemoteAPI.requests[7].resolve({});
195                 assert.equal(MockRemoteAPI.requests[8].method, 'GET');
196                 assert.equal(MockRemoteAPI.requests[8].url, '/json/builders/some%20builder%202/builds/?select=-1&select=-2');
197                 MockRemoteAPI.requests[8].resolve({});
198                 return syncPromise;
199             }).then(function () {
200                 assert.equal(BuildRequest.all().length, 4);
201                 assert.equal(BuildRequest.findById(700).status(), 'pending');
202                 assert.equal(BuildRequest.findById(700).statusUrl(), null);
203                 assert.equal(BuildRequest.findById(701).status(), 'pending');
204                 assert.equal(BuildRequest.findById(701).statusUrl(), null);
205                 assert.equal(BuildRequest.findById(702).status(), 'pending');
206                 assert.equal(BuildRequest.findById(702).statusUrl(), null);
207                 assert.equal(BuildRequest.findById(703).status(), 'pending');
208                 assert.equal(BuildRequest.findById(703).statusUrl(), null);
209                 return BuildRequest.fetchForTriggerable(MockData.mockTestSyncConfigWithTwoBuilders().triggerableName);
210             }).then(function () {
211                 assert.equal(BuildRequest.all().length, 4);
212                 assert.equal(BuildRequest.findById(700).status(), 'scheduled');
213                 assert.equal(BuildRequest.findById(700).statusUrl(), 'http://build.webkit.org/builders/some%20builder%202/');
214                 assert.equal(BuildRequest.findById(701).status(), 'pending');
215                 assert.equal(BuildRequest.findById(701).statusUrl(), null);
216                 assert.equal(BuildRequest.findById(702).status(), 'pending');
217                 assert.equal(BuildRequest.findById(702).statusUrl(), null);
218                 assert.equal(BuildRequest.findById(703).status(), 'pending');
219                 assert.equal(BuildRequest.findById(703).statusUrl(), null);
220                 done();
221             }).catch(done);
222         });
223
224         it('should not schedule a build request on a different builder than the one the first build request is pending', function (done) {
225             let db = TestServer.database();
226             let syncPromise;
227             db.connect().then(function () {
228                 return MockData.addMockData(db, ['pending', 'pending', 'pending', 'pending']);
229             }).then(function () {
230                 return Manifest.fetch();
231             }).then(function () {
232                 let config = MockData.mockTestSyncConfigWithTwoBuilders();
233                 let logger = new MockLogger;
234                 let slaveInfo = {name: 'sync-slave', password: 'password'};
235                 let triggerable = new BuildbotTriggerable(config, TestServer.remoteAPI(), MockRemoteAPI, slaveInfo, logger);
236                 syncPromise = triggerable.syncOnce();
237                 syncPromise.catch(done);
238                 return MockRemoteAPI.waitForRequest();
239             }).then(function () {
240                 assert.equal(MockRemoteAPI.requests.length, 2);
241                 assert.equal(MockRemoteAPI.requests[0].method, 'GET');
242                 assert.equal(MockRemoteAPI.requests[0].url, '/json/builders/some-builder-1/pendingBuilds');
243                 MockRemoteAPI.requests[0].resolve([MockData.pendingBuild({buildRequestId: 700})]);
244                 assert.equal(MockRemoteAPI.requests[1].method, 'GET');
245                 assert.equal(MockRemoteAPI.requests[1].url, '/json/builders/some%20builder%202/pendingBuilds');
246                 MockRemoteAPI.requests[1].resolve([]);
247                 return MockRemoteAPI.waitForRequest();
248             }).then(function () {
249                 assert.equal(MockRemoteAPI.requests.length, 4);
250                 assert.equal(MockRemoteAPI.requests[2].method, 'GET');
251                 assert.equal(MockRemoteAPI.requests[2].url, '/json/builders/some-builder-1/builds/?select=-1&select=-2');
252                 MockRemoteAPI.requests[2].resolve({});
253                 assert.equal(MockRemoteAPI.requests[3].method, 'GET');
254                 assert.equal(MockRemoteAPI.requests[3].url, '/json/builders/some%20builder%202/builds/?select=-1&select=-2');
255                 MockRemoteAPI.requests[3].resolve({});
256                 return MockRemoteAPI.waitForRequest();
257             }).then(function () {
258                 assert.equal(MockRemoteAPI.requests.length, 6);
259                 assert.equal(MockRemoteAPI.requests[4].method, 'GET');
260                 assert.equal(MockRemoteAPI.requests[4].url, '/json/builders/some-builder-1/pendingBuilds');
261                 MockRemoteAPI.requests[4].resolve([MockData.pendingBuild({buildRequestId: 700})]);
262                 assert.equal(MockRemoteAPI.requests[5].method, 'GET');
263                 assert.equal(MockRemoteAPI.requests[5].url, '/json/builders/some%20builder%202/pendingBuilds');
264                 MockRemoteAPI.requests[5].resolve([]);
265                 return MockRemoteAPI.waitForRequest();
266             }).then(function () {
267                 assert.equal(MockRemoteAPI.requests.length, 8);
268                 assert.equal(MockRemoteAPI.requests[6].method, 'GET');
269                 assert.equal(MockRemoteAPI.requests[6].url, '/json/builders/some-builder-1/builds/?select=-1&select=-2');
270                 MockRemoteAPI.requests[6].resolve({});
271                 assert.equal(MockRemoteAPI.requests[7].method, 'GET');
272                 assert.equal(MockRemoteAPI.requests[7].url, '/json/builders/some%20builder%202/builds/?select=-1&select=-2');
273                 MockRemoteAPI.requests[7].resolve({});
274                 return syncPromise;
275             }).then(function () {
276                 assert.equal(BuildRequest.all().length, 4);
277                 assert.equal(BuildRequest.findById(700).status(), 'pending');
278                 assert.equal(BuildRequest.findById(700).statusUrl(), null);
279                 assert.equal(BuildRequest.findById(701).status(), 'pending');
280                 assert.equal(BuildRequest.findById(701).statusUrl(), null);
281                 assert.equal(BuildRequest.findById(702).status(), 'pending');
282                 assert.equal(BuildRequest.findById(702).statusUrl(), null);
283                 assert.equal(BuildRequest.findById(703).status(), 'pending');
284                 assert.equal(BuildRequest.findById(703).statusUrl(), null);
285                 return BuildRequest.fetchForTriggerable(MockData.mockTestSyncConfigWithTwoBuilders().triggerableName);
286             }).then(function () {
287                 assert.equal(BuildRequest.all().length, 4);
288                 assert.equal(BuildRequest.findById(700).status(), 'scheduled');
289                 assert.equal(BuildRequest.findById(700).statusUrl(), 'http://build.webkit.org/builders/some-builder-1/');
290                 assert.equal(BuildRequest.findById(701).status(), 'pending');
291                 assert.equal(BuildRequest.findById(701).statusUrl(), null);
292                 assert.equal(BuildRequest.findById(702).status(), 'pending');
293                 assert.equal(BuildRequest.findById(702).statusUrl(), null);
294                 assert.equal(BuildRequest.findById(703).status(), 'pending');
295                 assert.equal(BuildRequest.findById(703).statusUrl(), null);
296                 done();
297             }).catch(done);
298         });
299
300         it('should update the status of a pending build and schedule a new build if the pending build had started running', function (done) {
301             let db = TestServer.database();
302             let syncPromise;
303             db.connect().then(function () {
304                 return MockData.addMockData(db, ['pending', 'pending', 'pending', 'pending']);
305             }).then(function () {
306                 return Manifest.fetch();
307             }).then(function () {
308                 let config = MockData.mockTestSyncConfigWithTwoBuilders();
309                 let logger = new MockLogger;
310                 let slaveInfo = {name: 'sync-slave', password: 'password'};
311                 let triggerable = new BuildbotTriggerable(config, TestServer.remoteAPI(), MockRemoteAPI, slaveInfo, logger);
312                 syncPromise = triggerable.syncOnce();
313                 syncPromise.catch(done);
314                 return MockRemoteAPI.waitForRequest();
315             }).then(function () {
316                 assert.equal(MockRemoteAPI.requests.length, 2);
317                 assert.equal(MockRemoteAPI.requests[0].method, 'GET');
318                 assert.equal(MockRemoteAPI.requests[0].url, '/json/builders/some-builder-1/pendingBuilds');
319                 MockRemoteAPI.requests[0].resolve([]);
320                 assert.equal(MockRemoteAPI.requests[1].method, 'GET');
321                 assert.equal(MockRemoteAPI.requests[1].url, '/json/builders/some%20builder%202/pendingBuilds');
322                 MockRemoteAPI.requests[1].resolve([]);
323                 return MockRemoteAPI.waitForRequest();
324             }).then(function () {
325                 assert.equal(MockRemoteAPI.requests.length, 4);
326                 assert.equal(MockRemoteAPI.requests[2].method, 'GET');
327                 assert.equal(MockRemoteAPI.requests[2].url, '/json/builders/some-builder-1/builds/?select=-1&select=-2');
328                 MockRemoteAPI.requests[2].resolve({[-1]: MockData.runningBuild({buildRequestId: 701}), [-2]: MockData.finishedBuild({buildRequestId: 700})});
329                 assert.equal(MockRemoteAPI.requests[3].method, 'GET');
330                 assert.equal(MockRemoteAPI.requests[3].url, '/json/builders/some%20builder%202/builds/?select=-1&select=-2');
331                 MockRemoteAPI.requests[3].resolve({});
332                 return MockRemoteAPI.waitForRequest();
333             }).then(function () {
334                 assert.equal(MockRemoteAPI.requests.length, 5);
335                 assert.equal(MockRemoteAPI.requests[4].method, 'POST');
336                 assert.equal(MockRemoteAPI.requests[4].url, '/builders/some-builder-1/force');
337                 assert.deepEqual(MockRemoteAPI.requests[4].data, {'wk': '191622', 'os': '10.11 15A284', 'build-request-id': '702'});
338                 MockRemoteAPI.requests[4].resolve('OK');
339                 return MockRemoteAPI.waitForRequest();
340             }).then(function () {
341                 assert.equal(MockRemoteAPI.requests.length, 7);
342                 assert.equal(MockRemoteAPI.requests[5].method, 'GET');
343                 assert.equal(MockRemoteAPI.requests[5].url, '/json/builders/some-builder-1/pendingBuilds');
344                 MockRemoteAPI.requests[5].resolve([MockData.pendingBuild({buildRequestId: 702})]);
345                 assert.equal(MockRemoteAPI.requests[6].method, 'GET');
346                 assert.equal(MockRemoteAPI.requests[6].url, '/json/builders/some%20builder%202/pendingBuilds');
347                 MockRemoteAPI.requests[6].resolve([]);
348                 return MockRemoteAPI.waitForRequest();
349             }).then(function () {
350                 assert.equal(MockRemoteAPI.requests.length, 9);
351                 assert.equal(MockRemoteAPI.requests[7].method, 'GET');
352                 assert.equal(MockRemoteAPI.requests[7].url, '/json/builders/some-builder-1/builds/?select=-1&select=-2');
353                 MockRemoteAPI.requests[7].resolve({[-1]: MockData.runningBuild({buildRequestId: 701}), [-2]: MockData.finishedBuild({buildRequestId: 700})});
354                 assert.equal(MockRemoteAPI.requests[8].method, 'GET');
355                 assert.equal(MockRemoteAPI.requests[8].url, '/json/builders/some%20builder%202/builds/?select=-1&select=-2');
356                 MockRemoteAPI.requests[8].resolve({});
357                 return syncPromise;
358             }).then(function () {
359                 assert.equal(BuildRequest.all().length, 4);
360                 assert.equal(BuildRequest.findById(700).status(), 'pending');
361                 assert.equal(BuildRequest.findById(700).statusUrl(), null);
362                 assert.equal(BuildRequest.findById(701).status(), 'pending');
363                 assert.equal(BuildRequest.findById(701).statusUrl(), null);
364                 assert.equal(BuildRequest.findById(702).status(), 'pending');
365                 assert.equal(BuildRequest.findById(702).statusUrl(), null);
366                 assert.equal(BuildRequest.findById(703).status(), 'pending');
367                 assert.equal(BuildRequest.findById(703).statusUrl(), null);
368                 return BuildRequest.fetchForTriggerable(MockData.mockTestSyncConfigWithTwoBuilders().triggerableName);
369             }).then(function () {
370                 assert.equal(BuildRequest.all().length, 4);
371                 assert.equal(BuildRequest.findById(700).status(), 'failed');
372                 assert.equal(BuildRequest.findById(700).statusUrl(), 'http://build.webkit.org/builders/some-builder-1/builds/123');
373                 assert.equal(BuildRequest.findById(701).status(), 'running');
374                 assert.equal(BuildRequest.findById(701).statusUrl(), 'http://build.webkit.org/builders/some-builder-1/builds/124');
375                 assert.equal(BuildRequest.findById(702).status(), 'scheduled');
376                 assert.equal(BuildRequest.findById(702).statusUrl(), 'http://build.webkit.org/builders/some-builder-1/');
377                 assert.equal(BuildRequest.findById(703).status(), 'pending');
378                 assert.equal(BuildRequest.findById(703).statusUrl(), null);
379                 done();
380             }).catch(done);
381         });
382
383         it('should update the status of a scheduled build if the pending build had started running', function (done) {
384             let db = TestServer.database();
385             let syncPromise;
386             db.connect().then(function () {
387                 return MockData.addMockData(db, ['scheduled', 'pending', 'pending', 'pending']);
388             }).then(function () {
389                 return Manifest.fetch();
390             }).then(function () {
391                 let config = MockData.mockTestSyncConfigWithSingleBuilder();
392                 let logger = new MockLogger;
393                 let slaveInfo = {name: 'sync-slave', password: 'password'};
394                 let triggerable = new BuildbotTriggerable(config, TestServer.remoteAPI(), MockRemoteAPI, slaveInfo, logger);
395                 syncPromise = triggerable.syncOnce();
396                 syncPromise.catch(done);
397                 return MockRemoteAPI.waitForRequest();
398             }).then(function () {
399                 assert.equal(MockRemoteAPI.requests.length, 1);
400                 assert.equal(MockRemoteAPI.requests[0].method, 'GET');
401                 assert.equal(MockRemoteAPI.requests[0].url, '/json/builders/some-builder-1/pendingBuilds');
402                 MockRemoteAPI.requests[0].resolve([MockData.pendingBuild({buildRequestId: 700})]);
403                 return MockRemoteAPI.waitForRequest();
404             }).then(function () {
405                 assert.equal(MockRemoteAPI.requests.length, 2);
406                 assert.equal(MockRemoteAPI.requests[1].method, 'GET');
407                 assert.equal(MockRemoteAPI.requests[1].url, '/json/builders/some-builder-1/builds/?select=-1&select=-2');
408                 MockRemoteAPI.requests[1].resolve({});
409                 return MockRemoteAPI.waitForRequest();
410             }).then(function () {
411                 assert.equal(MockRemoteAPI.requests.length, 3);
412                 assert.equal(MockRemoteAPI.requests[2].method, 'GET');
413                 assert.equal(MockRemoteAPI.requests[2].url, '/json/builders/some-builder-1/pendingBuilds');
414                 MockRemoteAPI.requests[2].resolve([]);
415                 return MockRemoteAPI.waitForRequest();
416             }).then(function () {
417                 assert.equal(MockRemoteAPI.requests.length, 4);
418                 assert.equal(MockRemoteAPI.requests[3].method, 'GET');
419                 assert.equal(MockRemoteAPI.requests[3].url, '/json/builders/some-builder-1/builds/?select=-1&select=-2');
420                 MockRemoteAPI.requests[3].resolve({[-1]: MockData.runningBuild({buildRequestId: 700})});
421                 return syncPromise;
422             }).then(function () {
423                 assert.equal(BuildRequest.all().length, 4);
424                 assert.equal(BuildRequest.findById(700).status(), 'scheduled');
425                 assert.equal(BuildRequest.findById(700).statusUrl(), null);
426                 assert.equal(BuildRequest.findById(701).status(), 'pending');
427                 assert.equal(BuildRequest.findById(701).statusUrl(), null);
428                 assert.equal(BuildRequest.findById(702).status(), 'pending');
429                 assert.equal(BuildRequest.findById(702).statusUrl(), null);
430                 assert.equal(BuildRequest.findById(703).status(), 'pending');
431                 assert.equal(BuildRequest.findById(703).statusUrl(), null);
432                 return BuildRequest.fetchForTriggerable(MockData.mockTestSyncConfigWithTwoBuilders().triggerableName);
433             }).then(function () {
434                 assert.equal(BuildRequest.all().length, 4);
435                 assert.equal(BuildRequest.findById(700).status(), 'running');
436                 assert.equal(BuildRequest.findById(700).statusUrl(), 'http://build.webkit.org/builders/some-builder-1/builds/124');
437                 assert.equal(BuildRequest.findById(701).status(), 'pending');
438                 assert.equal(BuildRequest.findById(701).statusUrl(), null);
439                 assert.equal(BuildRequest.findById(702).status(), 'pending');
440                 assert.equal(BuildRequest.findById(702).statusUrl(), null);
441                 assert.equal(BuildRequest.findById(703).status(), 'pending');
442                 assert.equal(BuildRequest.findById(703).statusUrl(), null);
443                 done();
444             }).catch(done);
445         });
446
447         it('should schedule a build request on a builder without pending builds if the request belongs to a new test group', function (done) {
448             let db = TestServer.database();
449             let syncPromise;
450             db.connect().then(function () {
451                 return Promise.all([
452                     MockData.addMockData(db, ['completed', 'pending', 'pending', 'pending']),
453                     MockData.addAnotherMockTestGroup(db, ['pending', 'pending', 'pending', 'pending'])
454                 ]);
455             }).then(function () {
456                 return Manifest.fetch();
457             }).then(function () {
458                 let config = MockData.mockTestSyncConfigWithTwoBuilders();
459                 let logger = new MockLogger;
460                 let slaveInfo = {name: 'sync-slave', password: 'password'};
461                 let triggerable = new BuildbotTriggerable(config, TestServer.remoteAPI(), MockRemoteAPI, slaveInfo, logger);
462                 syncPromise = triggerable.syncOnce();
463                 syncPromise.catch(done);
464                 return MockRemoteAPI.waitForRequest();
465             }).then(function () {
466                 assert.equal(MockRemoteAPI.requests.length, 2);
467                 assert.equal(MockRemoteAPI.requests[0].method, 'GET');
468                 assert.equal(MockRemoteAPI.requests[0].url, '/json/builders/some-builder-1/pendingBuilds');
469                 MockRemoteAPI.requests[0].resolve([MockData.pendingBuild({buildRequestId: 702})]);
470                 assert.equal(MockRemoteAPI.requests[1].method, 'GET');
471                 assert.equal(MockRemoteAPI.requests[1].url, '/json/builders/some%20builder%202/pendingBuilds');
472                 MockRemoteAPI.requests[1].resolve([]);
473                 return MockRemoteAPI.waitForRequest();
474             }).then(function () {
475                 assert.equal(MockRemoteAPI.requests.length, 4);
476                 assert.equal(MockRemoteAPI.requests[2].method, 'GET');
477                 assert.equal(MockRemoteAPI.requests[2].url, '/json/builders/some-builder-1/builds/?select=-1&select=-2');
478                 MockRemoteAPI.requests[2].resolve({[-1]: MockData.runningBuild({buildRequestId: 701}), [-2]: MockData.finishedBuild({buildRequestId: 700})});
479                 assert.equal(MockRemoteAPI.requests[3].method, 'GET');
480                 assert.equal(MockRemoteAPI.requests[3].url, '/json/builders/some%20builder%202/builds/?select=-1&select=-2');
481                 MockRemoteAPI.requests[3].resolve({});
482                 return MockRemoteAPI.waitForRequest();
483             }).then(function () {
484                 assert.equal(MockRemoteAPI.requests.length, 5);
485                 assert.equal(MockRemoteAPI.requests[4].method, 'POST');
486                 assert.equal(MockRemoteAPI.requests[4].url, '/builders/some%20builder%202/force');
487                 assert.deepEqual(MockRemoteAPI.requests[4].data, {'wk': '191622', 'os': '10.11 15A284', 'build-request-id': '710'});
488                 MockRemoteAPI.requests[4].resolve('OK');
489                 return MockRemoteAPI.waitForRequest();
490             }).then(function () {
491                 assert.equal(MockRemoteAPI.requests.length, 7);
492                 assert.equal(MockRemoteAPI.requests[5].method, 'GET');
493                 assert.equal(MockRemoteAPI.requests[5].url, '/json/builders/some-builder-1/pendingBuilds');
494                 MockRemoteAPI.requests[5].resolve([MockData.pendingBuild({buildRequestId: 702})]);
495                 assert.equal(MockRemoteAPI.requests[6].method, 'GET');
496                 assert.equal(MockRemoteAPI.requests[6].url, '/json/builders/some%20builder%202/pendingBuilds');
497                 MockRemoteAPI.requests[6].resolve([MockData.pendingBuild({builder: 'some builder 2', buildRequestId: 710})]);
498                 return MockRemoteAPI.waitForRequest();
499             }).then(function () {
500                 assert.equal(MockRemoteAPI.requests.length, 9);
501                 assert.equal(MockRemoteAPI.requests[7].method, 'GET');
502                 assert.equal(MockRemoteAPI.requests[7].url, '/json/builders/some-builder-1/builds/?select=-1&select=-2');
503                 MockRemoteAPI.requests[7].resolve({[-1]: MockData.runningBuild({buildRequestId: 701}), [-2]: MockData.finishedBuild({buildRequestId: 700})});
504                 assert.equal(MockRemoteAPI.requests[8].method, 'GET');
505                 assert.equal(MockRemoteAPI.requests[8].url, '/json/builders/some%20builder%202/builds/?select=-1&select=-2');
506                 MockRemoteAPI.requests[8].resolve({});
507                 return syncPromise;
508             }).then(function () {
509                 assert.equal(BuildRequest.all().length, 8);
510                 assert.equal(BuildRequest.findById(700).status(), 'completed');
511                 assert.equal(BuildRequest.findById(700).statusUrl(), null);
512                 assert.equal(BuildRequest.findById(701).status(), 'pending');
513                 assert.equal(BuildRequest.findById(701).statusUrl(), null);
514                 assert.equal(BuildRequest.findById(702).status(), 'pending');
515                 assert.equal(BuildRequest.findById(702).statusUrl(), null);
516                 assert.equal(BuildRequest.findById(703).status(), 'pending');
517                 assert.equal(BuildRequest.findById(703).statusUrl(), null);
518                 assert.equal(BuildRequest.findById(710).status(), 'pending');
519                 assert.equal(BuildRequest.findById(710).statusUrl(), null);
520                 assert.equal(BuildRequest.findById(711).status(), 'pending');
521                 assert.equal(BuildRequest.findById(711).statusUrl(), null);
522                 assert.equal(BuildRequest.findById(712).status(), 'pending');
523                 assert.equal(BuildRequest.findById(712).statusUrl(), null);
524                 assert.equal(BuildRequest.findById(713).status(), 'pending');
525                 assert.equal(BuildRequest.findById(713).statusUrl(), null);
526                 return BuildRequest.fetchForTriggerable(MockData.mockTestSyncConfigWithTwoBuilders().triggerableName);
527             }).then(function () {
528                 assert.equal(BuildRequest.all().length, 8);
529                 assert.equal(BuildRequest.findById(700).status(), 'completed');
530                 assert.equal(BuildRequest.findById(700).statusUrl(), 'http://build.webkit.org/builders/some-builder-1/builds/123');
531                 assert.equal(BuildRequest.findById(701).status(), 'running');
532                 assert.equal(BuildRequest.findById(701).statusUrl(), 'http://build.webkit.org/builders/some-builder-1/builds/124');
533                 assert.equal(BuildRequest.findById(702).status(), 'scheduled');
534                 assert.equal(BuildRequest.findById(702).statusUrl(), 'http://build.webkit.org/builders/some-builder-1/');
535                 assert.equal(BuildRequest.findById(703).status(), 'pending');
536                 assert.equal(BuildRequest.findById(703).statusUrl(), null);
537                 assert.equal(BuildRequest.findById(710).status(), 'scheduled');
538                 assert.equal(BuildRequest.findById(710).statusUrl(), 'http://build.webkit.org/builders/some%20builder%202/');
539                 assert.equal(BuildRequest.findById(711).status(), 'pending');
540                 assert.equal(BuildRequest.findById(711).statusUrl(), null);
541                 assert.equal(BuildRequest.findById(712).status(), 'pending');
542                 assert.equal(BuildRequest.findById(712).statusUrl(), null);
543                 assert.equal(BuildRequest.findById(713).status(), 'pending');
544                 assert.equal(BuildRequest.findById(713).statusUrl(), null);
545                 done();
546             }).catch(done);
547         });
548
549         it('should schedule a build request on the same scheduler the first request had ran', function (done) {
550             let db = TestServer.database();
551             let syncPromise;
552             db.connect().then(function () {
553                 return Promise.all([
554                     MockData.addMockData(db, ['running', 'pending', 'pending', 'pending']),
555                     MockData.addAnotherMockTestGroup(db, ['running', 'pending', 'pending', 'pending'])
556                 ]);
557             }).then(function () {
558                 return Manifest.fetch();
559             }).then(function () {
560                 let config = MockData.mockTestSyncConfigWithTwoBuilders();
561                 let logger = new MockLogger;
562                 let slaveInfo = {name: 'sync-slave', password: 'password'};
563                 let triggerable = new BuildbotTriggerable(config, TestServer.remoteAPI(), MockRemoteAPI, slaveInfo, logger);
564                 syncPromise = triggerable.syncOnce();
565                 syncPromise.catch(done);
566                 return MockRemoteAPI.waitForRequest();
567             }).then(function () {
568                 assert.equal(MockRemoteAPI.requests.length, 2);
569                 assert.equal(MockRemoteAPI.requests[0].method, 'GET');
570                 assert.equal(MockRemoteAPI.requests[0].url, '/json/builders/some-builder-1/pendingBuilds');
571                 MockRemoteAPI.requests[0].resolve([]);
572                 assert.equal(MockRemoteAPI.requests[1].method, 'GET');
573                 assert.equal(MockRemoteAPI.requests[1].url, '/json/builders/some%20builder%202/pendingBuilds');
574                 MockRemoteAPI.requests[1].resolve([]);
575                 return MockRemoteAPI.waitForRequest();
576             }).then(function () {
577                 assert.equal(MockRemoteAPI.requests.length, 4);
578                 assert.equal(MockRemoteAPI.requests[2].method, 'GET');
579                 assert.equal(MockRemoteAPI.requests[2].url, '/json/builders/some-builder-1/builds/?select=-1&select=-2');
580                 MockRemoteAPI.requests[2].resolve({[-1]: MockData.runningBuild({buildRequestId: 710})});
581                 assert.equal(MockRemoteAPI.requests[3].method, 'GET');
582                 assert.equal(MockRemoteAPI.requests[3].url, '/json/builders/some%20builder%202/builds/?select=-1&select=-2');
583                 MockRemoteAPI.requests[3].resolve({[-1]: MockData.runningBuild({builder: 'some builder 2', buildRequestId: 700})});
584                 return MockRemoteAPI.waitForRequest();
585             }).then(function () {
586                 assert.equal(MockRemoteAPI.requests.length, 6);
587                 assert.equal(MockRemoteAPI.requests[4].method, 'POST');
588                 assert.equal(MockRemoteAPI.requests[4].url, '/builders/some%20builder%202/force');
589                 assert.deepEqual(MockRemoteAPI.requests[4].data, {'wk': '192736', 'os': '10.11 15A284', 'build-request-id': '701'});
590                 MockRemoteAPI.requests[4].resolve('OK');
591                 assert.equal(MockRemoteAPI.requests[5].method, 'POST');
592                 assert.equal(MockRemoteAPI.requests[5].url, '/builders/some-builder-1/force');
593                 assert.deepEqual(MockRemoteAPI.requests[5].data, {'wk': '192736', 'os': '10.11 15A284', 'build-request-id': '711'});
594                 MockRemoteAPI.requests[5].resolve('OK');
595                 return MockRemoteAPI.waitForRequest();
596             }).then(function () {
597                 assert.equal(MockRemoteAPI.requests.length, 8);
598                 assert.equal(MockRemoteAPI.requests[6].method, 'GET');
599                 assert.equal(MockRemoteAPI.requests[6].url, '/json/builders/some-builder-1/pendingBuilds');
600                 MockRemoteAPI.requests[6].resolve([MockData.pendingBuild({buildRequestId: 711})]);
601                 assert.equal(MockRemoteAPI.requests[7].method, 'GET');
602                 assert.equal(MockRemoteAPI.requests[7].url, '/json/builders/some%20builder%202/pendingBuilds');
603                 MockRemoteAPI.requests[7].resolve([MockData.pendingBuild({builder: 'some builder 2',buildRequestId: 701})]);
604                 return MockRemoteAPI.waitForRequest();
605             }).then(function () {
606                 assert.equal(MockRemoteAPI.requests.length, 10);
607                 assert.equal(MockRemoteAPI.requests[8].method, 'GET');
608                 assert.equal(MockRemoteAPI.requests[8].url, '/json/builders/some-builder-1/builds/?select=-1&select=-2');
609                 MockRemoteAPI.requests[8].resolve({[-1]: MockData.runningBuild({buildRequestId: 710})});
610                 assert.equal(MockRemoteAPI.requests[9].method, 'GET');
611                 assert.equal(MockRemoteAPI.requests[9].url, '/json/builders/some%20builder%202/builds/?select=-1&select=-2');
612                 MockRemoteAPI.requests[9].resolve({[-1]: MockData.runningBuild({builder: 'some builder 2', buildRequestId: 700})});
613                 return syncPromise;
614             }).then(function () {
615                 assert.equal(BuildRequest.all().length, 8);
616                 assert.equal(BuildRequest.findById(700).status(), 'running');
617                 assert.equal(BuildRequest.findById(700).statusUrl(), null);
618                 assert.equal(BuildRequest.findById(701).status(), 'pending');
619                 assert.equal(BuildRequest.findById(701).statusUrl(), null);
620                 assert.equal(BuildRequest.findById(702).status(), 'pending');
621                 assert.equal(BuildRequest.findById(702).statusUrl(), null);
622                 assert.equal(BuildRequest.findById(703).status(), 'pending');
623                 assert.equal(BuildRequest.findById(703).statusUrl(), null);
624                 assert.equal(BuildRequest.findById(710).status(), 'running');
625                 assert.equal(BuildRequest.findById(710).statusUrl(), null);
626                 assert.equal(BuildRequest.findById(711).status(), 'pending');
627                 assert.equal(BuildRequest.findById(711).statusUrl(), null);
628                 assert.equal(BuildRequest.findById(712).status(), 'pending');
629                 assert.equal(BuildRequest.findById(712).statusUrl(), null);
630                 assert.equal(BuildRequest.findById(713).status(), 'pending');
631                 assert.equal(BuildRequest.findById(713).statusUrl(), null);
632                 return BuildRequest.fetchForTriggerable(MockData.mockTestSyncConfigWithTwoBuilders().triggerableName);
633             }).then(function () {
634                 assert.equal(BuildRequest.all().length, 8);
635                 assert.equal(BuildRequest.findById(700).status(), 'running');
636                 assert.equal(BuildRequest.findById(700).statusUrl(), 'http://build.webkit.org/builders/some%20builder%202/builds/124');
637                 assert.equal(BuildRequest.findById(701).status(), 'scheduled');
638                 assert.equal(BuildRequest.findById(701).statusUrl(), 'http://build.webkit.org/builders/some%20builder%202/');
639                 assert.equal(BuildRequest.findById(702).status(), 'pending');
640                 assert.equal(BuildRequest.findById(702).statusUrl(), null);
641                 assert.equal(BuildRequest.findById(703).status(), 'pending');
642                 assert.equal(BuildRequest.findById(703).statusUrl(), null);
643                 assert.equal(BuildRequest.findById(710).status(), 'running');
644                 assert.equal(BuildRequest.findById(710).statusUrl(), 'http://build.webkit.org/builders/some-builder-1/builds/124');
645                 assert.equal(BuildRequest.findById(711).status(), 'scheduled');
646                 assert.equal(BuildRequest.findById(711).statusUrl(), 'http://build.webkit.org/builders/some-builder-1/');
647                 assert.equal(BuildRequest.findById(712).status(), 'pending');
648                 assert.equal(BuildRequest.findById(712).statusUrl(), null);
649                 assert.equal(BuildRequest.findById(713).status(), 'pending');
650                 assert.equal(BuildRequest.findById(713).statusUrl(), null);
651                 done();
652             }).catch(done);
653         });
654
655         it('should recover from multiple test groups running simultenously', function (done) {
656             let db = TestServer.database();
657             let syncPromise;
658             db.connect().then(function () {
659                 return Promise.all([
660                     MockData.addMockData(db, ['completed', 'pending', 'pending', 'pending']),
661                     MockData.addAnotherMockTestGroup(db, ['completed', 'pending', 'pending', 'pending'])
662                 ]);
663             }).then(function () {
664                 return Manifest.fetch();
665             }).then(function () {
666                 let config = MockData.mockTestSyncConfigWithSingleBuilder();
667                 let logger = new MockLogger;
668                 let slaveInfo = {name: 'sync-slave', password: 'password'};
669                 let triggerable = new BuildbotTriggerable(config, TestServer.remoteAPI(), MockRemoteAPI, slaveInfo, logger);
670                 syncPromise = triggerable.syncOnce();
671                 syncPromise.catch(done);
672                 return MockRemoteAPI.waitForRequest();
673             }).then(function () {
674                 assert.equal(MockRemoteAPI.requests.length, 1);
675                 assert.equal(MockRemoteAPI.requests[0].method, 'GET');
676                 assert.equal(MockRemoteAPI.requests[0].url, '/json/builders/some-builder-1/pendingBuilds');
677                 MockRemoteAPI.requests[0].resolve([MockData.pendingBuild({buildRequestId: 711})]);
678                 return MockRemoteAPI.waitForRequest();
679             }).then(function () {
680                 assert.equal(MockRemoteAPI.requests.length, 2);
681                 assert.equal(MockRemoteAPI.requests[1].method, 'GET');
682                 assert.equal(MockRemoteAPI.requests[1].url, '/json/builders/some-builder-1/builds/?select=-1&select=-2');
683                 MockRemoteAPI.requests[1].resolve({[-1]: MockData.runningBuild({buildRequestId: 700}), [-2]: MockData.finishedBuild({buildRequestId: 710})});
684                 return MockRemoteAPI.waitForRequest();
685             }).then(function () {
686                 assert.equal(MockRemoteAPI.requests.length, 3);
687                 assert.equal(MockRemoteAPI.requests[2].method, 'GET');
688                 assert.equal(MockRemoteAPI.requests[2].url, '/json/builders/some-builder-1/pendingBuilds');
689                 MockRemoteAPI.requests[2].resolve([MockData.pendingBuild({buildRequestId: 701})]);
690                 return MockRemoteAPI.waitForRequest();
691             }).then(function () {
692                 assert.equal(MockRemoteAPI.requests.length, 4);
693                 assert.equal(MockRemoteAPI.requests[3].method, 'GET');
694                 assert.equal(MockRemoteAPI.requests[3].url, '/json/builders/some-builder-1/builds/?select=-1&select=-2');
695                 MockRemoteAPI.requests[3].resolve({[-1]: MockData.runningBuild({buildRequestId: 700}), [-2]: MockData.finishedBuild({buildRequestId: 710})});
696                 return syncPromise;
697             }).then(function () {
698                 assert.equal(BuildRequest.all().length, 8);
699                 assert.equal(BuildRequest.findById(700).status(), 'completed');
700                 assert.equal(BuildRequest.findById(700).statusUrl(), null);
701                 assert.equal(BuildRequest.findById(701).status(), 'pending');
702                 assert.equal(BuildRequest.findById(701).statusUrl(), null);
703                 assert.equal(BuildRequest.findById(702).status(), 'pending');
704                 assert.equal(BuildRequest.findById(702).statusUrl(), null);
705                 assert.equal(BuildRequest.findById(703).status(), 'pending');
706                 assert.equal(BuildRequest.findById(703).statusUrl(), null);
707                 assert.equal(BuildRequest.findById(710).status(), 'completed');
708                 assert.equal(BuildRequest.findById(710).statusUrl(), null);
709                 assert.equal(BuildRequest.findById(711).status(), 'pending');
710                 assert.equal(BuildRequest.findById(711).statusUrl(), null);
711                 assert.equal(BuildRequest.findById(712).status(), 'pending');
712                 assert.equal(BuildRequest.findById(712).statusUrl(), null);
713                 assert.equal(BuildRequest.findById(713).status(), 'pending');
714                 assert.equal(BuildRequest.findById(713).statusUrl(), null);
715                 return BuildRequest.fetchForTriggerable(MockData.mockTestSyncConfigWithTwoBuilders().triggerableName);
716             }).then(function () {
717                 assert.equal(BuildRequest.all().length, 8);
718                 assert.equal(BuildRequest.findById(700).status(), 'completed');
719                 assert.equal(BuildRequest.findById(700).statusUrl(), 'http://build.webkit.org/builders/some-builder-1/builds/124');
720                 assert.equal(BuildRequest.findById(701).status(), 'scheduled');
721                 assert.equal(BuildRequest.findById(701).statusUrl(), 'http://build.webkit.org/builders/some-builder-1/');
722                 assert.equal(BuildRequest.findById(702).status(), 'pending');
723                 assert.equal(BuildRequest.findById(702).statusUrl(), null);
724                 assert.equal(BuildRequest.findById(703).status(), 'pending');
725                 assert.equal(BuildRequest.findById(703).statusUrl(), null);
726                 assert.equal(BuildRequest.findById(710).status(), 'completed');
727                 assert.equal(BuildRequest.findById(710).statusUrl(), 'http://build.webkit.org/builders/some-builder-1/builds/123');
728                 assert.equal(BuildRequest.findById(711).status(), 'pending');
729                 assert.equal(BuildRequest.findById(711).statusUrl(), null);
730                 assert.equal(BuildRequest.findById(712).status(), 'pending');
731                 assert.equal(BuildRequest.findById(712).statusUrl(), null);
732                 assert.equal(BuildRequest.findById(713).status(), 'pending');
733                 assert.equal(BuildRequest.findById(713).statusUrl(), null);
734                 done();
735             }).catch(done);
736         });
737
738         it('should recover from missing failed build request', function (done) {
739             let db = TestServer.database();
740             let syncPromise;
741             db.connect().then(function () {
742                 return Promise.all([
743                     MockData.addMockData(db, ['failed', 'pending', 'pending', 'pending']),
744                 ]);
745             }).then(function () {
746                 return Manifest.fetch();
747             }).then(function () {
748                 let config = MockData.mockTestSyncConfigWithSingleBuilder();
749                 let logger = new MockLogger;
750                 let slaveInfo = {name: 'sync-slave', password: 'password'};
751                 let triggerable = new BuildbotTriggerable(config, TestServer.remoteAPI(), MockRemoteAPI, slaveInfo, logger);
752                 syncPromise = triggerable.syncOnce();
753                 syncPromise.catch(done);
754                 return MockRemoteAPI.waitForRequest();
755             }).then(function () {
756                 assert.equal(MockRemoteAPI.requests.length, 1);
757                 assert.equal(MockRemoteAPI.requests[0].method, 'GET');
758                 assert.equal(MockRemoteAPI.requests[0].url, '/json/builders/some-builder-1/pendingBuilds');
759                 MockRemoteAPI.requests[0].resolve([]);
760                 return MockRemoteAPI.waitForRequest();
761             }).then(function () {
762                 assert.equal(MockRemoteAPI.requests.length, 2);
763                 assert.equal(MockRemoteAPI.requests[1].method, 'GET');
764                 assert.equal(MockRemoteAPI.requests[1].url, '/json/builders/some-builder-1/builds/?select=-1&select=-2');
765                 MockRemoteAPI.requests[1].resolve({});
766                 return MockRemoteAPI.waitForRequest();
767             }).then(function () {
768                 assert.equal(MockRemoteAPI.requests.length, 3);
769                 assert.equal(MockRemoteAPI.requests[2].method, 'POST');
770                 assert.equal(MockRemoteAPI.requests[2].url, '/builders/some-builder-1/force');
771                 assert.deepEqual(MockRemoteAPI.requests[2].data, {'wk': '192736', 'os': '10.11 15A284', 'build-request-id': '701'});
772                 MockRemoteAPI.requests[2].resolve('OK');
773                 return MockRemoteAPI.waitForRequest();
774             }).then(function () {
775                 assert.equal(MockRemoteAPI.requests.length, 4);
776                 assert.equal(MockRemoteAPI.requests[3].method, 'GET');
777                 assert.equal(MockRemoteAPI.requests[3].url, '/json/builders/some-builder-1/pendingBuilds');
778                 MockRemoteAPI.requests[3].resolve([MockData.pendingBuild({buildRequestId: 701})]);
779                 return MockRemoteAPI.waitForRequest();
780             }).then(function () {
781                 assert.equal(MockRemoteAPI.requests.length, 5);
782                 assert.equal(MockRemoteAPI.requests[4].method, 'GET');
783                 assert.equal(MockRemoteAPI.requests[4].url, '/json/builders/some-builder-1/builds/?select=-1&select=-2');
784                 MockRemoteAPI.requests[4].resolve({});
785                 return syncPromise;
786             }).then(function () {
787                 assert.equal(BuildRequest.all().length, 4);
788                 assert.equal(BuildRequest.findById(700).status(), 'failed');
789                 assert.equal(BuildRequest.findById(700).statusUrl(), null);
790                 assert.equal(BuildRequest.findById(701).status(), 'pending');
791                 assert.equal(BuildRequest.findById(701).statusUrl(), null);
792                 assert.equal(BuildRequest.findById(702).status(), 'pending');
793                 assert.equal(BuildRequest.findById(702).statusUrl(), null);
794                 assert.equal(BuildRequest.findById(703).status(), 'pending');
795                 assert.equal(BuildRequest.findById(703).statusUrl(), null);
796                 return BuildRequest.fetchForTriggerable(MockData.mockTestSyncConfigWithTwoBuilders().triggerableName);
797             }).then(function () {
798                 assert.equal(BuildRequest.all().length, 4);
799                 assert.equal(BuildRequest.findById(700).status(), 'failed');
800                 assert.equal(BuildRequest.findById(700).statusUrl(), null);
801                 assert.equal(BuildRequest.findById(701).status(), 'scheduled');
802                 assert.equal(BuildRequest.findById(701).statusUrl(), 'http://build.webkit.org/builders/some-builder-1/');
803                 assert.equal(BuildRequest.findById(702).status(), 'pending');
804                 assert.equal(BuildRequest.findById(702).statusUrl(), null);
805                 assert.equal(BuildRequest.findById(703).status(), 'pending');
806                 assert.equal(BuildRequest.findById(703).statusUrl(), null);
807                 done();
808             }).catch(done);
809         });
810
811         it('should update the status of a supposedly scheduled build that went missing', function (done) {
812             let db = TestServer.database();
813             let syncPromise;
814             db.connect().then(function () {
815                 return MockData.addMockData(db, ['scheduled', 'pending', 'pending', 'pending']);
816             }).then(function () {
817                 return Manifest.fetch();
818             }).then(function () {
819                 let config = MockData.mockTestSyncConfigWithSingleBuilder();
820                 let logger = new MockLogger;
821                 let slaveInfo = {name: 'sync-slave', password: 'password'};
822                 let triggerable = new BuildbotTriggerable(config, TestServer.remoteAPI(), MockRemoteAPI, slaveInfo, logger);
823                 syncPromise = triggerable.syncOnce();
824                 syncPromise.catch(done);
825                 return MockRemoteAPI.waitForRequest();
826             }).then(function () {
827                 assert.equal(MockRemoteAPI.requests.length, 1);
828                 assert.equal(MockRemoteAPI.requests[0].method, 'GET');
829                 assert.equal(MockRemoteAPI.requests[0].url, '/json/builders/some-builder-1/pendingBuilds');
830                 MockRemoteAPI.requests[0].resolve([]);
831                 return MockRemoteAPI.waitForRequest();
832             }).then(function () {
833                 assert.equal(MockRemoteAPI.requests.length, 2);
834                 assert.equal(MockRemoteAPI.requests[1].method, 'GET');
835                 assert.equal(MockRemoteAPI.requests[1].url, '/json/builders/some-builder-1/builds/?select=-1&select=-2');
836                 MockRemoteAPI.requests[1].resolve({});
837                 return MockRemoteAPI.waitForRequest();
838             }).then(function () {
839                 assert.equal(MockRemoteAPI.requests.length, 3);
840                 assert.equal(MockRemoteAPI.requests[2].method, 'GET');
841                 assert.equal(MockRemoteAPI.requests[2].url, '/json/builders/some-builder-1/pendingBuilds');
842                 MockRemoteAPI.requests[2].resolve([]);
843                 return MockRemoteAPI.waitForRequest();
844             }).then(function () {
845                 assert.equal(MockRemoteAPI.requests.length, 4);
846                 assert.equal(MockRemoteAPI.requests[3].method, 'GET');
847                 assert.equal(MockRemoteAPI.requests[3].url, '/json/builders/some-builder-1/builds/?select=-1&select=-2');
848                 MockRemoteAPI.requests[3].resolve({});
849                 return syncPromise;
850             }).then(function () {
851                 assert.equal(BuildRequest.all().length, 4);
852                 assert.equal(BuildRequest.findById(700).status(), 'scheduled');
853                 assert.equal(BuildRequest.findById(701).status(), 'pending');
854                 assert.equal(BuildRequest.findById(702).status(), 'pending');
855                 assert.equal(BuildRequest.findById(703).status(), 'pending');
856                 return BuildRequest.fetchForTriggerable(MockData.mockTestSyncConfigWithTwoBuilders().triggerableName);
857             }).then(function () {
858                 assert.equal(BuildRequest.all().length, 4);
859                 assert.equal(BuildRequest.findById(700).status(), 'failed');
860                 assert.equal(BuildRequest.findById(701).status(), 'pending');
861                 assert.equal(BuildRequest.findById(702).status(), 'pending');
862                 assert.equal(BuildRequest.findById(703).status(), 'pending');
863                 done();
864             }).catch(done);
865         });
866
867         it('should schedule a build request of an user created test group before ones created by automatic change detection', function (done) {
868             let db = TestServer.database();
869             let syncPromise;
870             db.connect().then(function () {
871                 return Promise.all([
872                     MockData.addMockData(db, ['pending', 'pending', 'pending', 'pending']),
873                     MockData.addAnotherMockTestGroup(db, ['pending', 'pending', 'pending', 'pending'], 'rniwa'),
874                 ]);
875             }).then(function () {
876                 return Manifest.fetch();
877             }).then(function () {
878                 let config = MockData.mockTestSyncConfigWithSingleBuilder();
879                 let logger = new MockLogger;
880                 let slaveInfo = {name: 'sync-slave', password: 'password'};
881                 let triggerable = new BuildbotTriggerable(config, TestServer.remoteAPI(), MockRemoteAPI, slaveInfo, logger);
882                 syncPromise = triggerable.syncOnce();
883                 syncPromise.catch(done);
884                 return MockRemoteAPI.waitForRequest();
885             }).then(function () {
886                 assert.equal(MockRemoteAPI.requests.length, 1);
887                 assert.equal(MockRemoteAPI.requests[0].method, 'GET');
888                 assert.equal(MockRemoteAPI.requests[0].url, '/json/builders/some-builder-1/pendingBuilds');
889                 MockRemoteAPI.requests[0].resolve([]);
890                 return MockRemoteAPI.waitForRequest();
891             }).then(function () {
892                 assert.equal(MockRemoteAPI.requests.length, 2);
893                 assert.equal(MockRemoteAPI.requests[1].method, 'GET');
894                 assert.equal(MockRemoteAPI.requests[1].url, '/json/builders/some-builder-1/builds/?select=-1&select=-2');
895                 MockRemoteAPI.requests[1].resolve({});
896                 return MockRemoteAPI.waitForRequest();
897             }).then(function () {
898                 assert.equal(MockRemoteAPI.requests.length, 3);
899                 assert.equal(MockRemoteAPI.requests[2].method, 'POST');
900                 assert.equal(MockRemoteAPI.requests[2].url, '/builders/some-builder-1/force');
901                 assert.deepEqual(MockRemoteAPI.requests[2].data, {'wk': '191622', 'os': '10.11 15A284', 'build-request-id': '710'});
902                 MockRemoteAPI.requests[2].resolve('OK');
903                 done();
904             }).catch(done);
905         });
906     });
907
908     describe('updateTriggerables', function () {
909         connectToDatabaseInEveryTest();
910
911         it('should update available triggerables', function (done) {
912             let db = TestServer.database();
913             MockData.addMockData(db).then(function () {
914                 return Manifest.fetch();
915             }).then(function () {
916                 return db.selectAll('triggerable_configurations', 'test');
917             }).then(function (configurations) {
918                 assert.equal(configurations.length, 0);
919                 let config = MockData.mockTestSyncConfigWithSingleBuilder();
920                 let logger = new MockLogger;
921                 let slaveInfo = {name: 'sync-slave', password: 'password'};
922                 let triggerable = new BuildbotTriggerable(config, TestServer.remoteAPI(), MockRemoteAPI, slaveInfo, logger);
923                 return triggerable.updateTriggerable();
924             }).then(function () {
925                 return db.selectAll('triggerable_configurations', 'test');
926             }).then(function (configurations) {
927                 assert.equal(configurations.length, 1);
928                 assert.equal(configurations[0].test, MockData.someTestId());
929                 assert.equal(configurations[0].platform, MockData.somePlatformId());
930                 done();
931             }).catch(done);
932         });
933     });
934
935 });