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