Extend create-analysis-test API to be able to create with confirming test group.
[WebKit-https.git] / Websites / perf.webkit.org / server-tests / privileged-api-create-analysis-task-tests.js
1 'use strict';
2
3 let assert = require('assert');
4
5 let MockData = require('./resources/mock-data.js');
6 let TestServer = require('./resources/test-server.js');
7 const addBuilderForReport = require('./resources/common-operations.js').addBuilderForReport;
8 const prepareServerTest = require('./resources/common-operations.js').prepareServerTest;
9
10 const reportWithRevision = [{
11     "buildNumber": "124",
12     "buildTime": "2015-10-27T15:34:51",
13     "revisions": {
14         "WebKit": {
15             "revision": "191622",
16             "timestamp": '2015-10-27T11:36:56.878473Z',
17         },
18     },
19     "builderName": "someBuilder",
20     "builderPassword": "somePassword",
21     "platform": "some platform",
22     "tests": {
23         "Suite": {
24             "metrics": {
25                 "Time": ["Arithmetic"],
26             },
27             "tests": {
28                 "test1": {
29                     "metrics": {"Time": { "current": [11] }},
30                 }
31             }
32         },
33     }}];
34
35 const reportWithRevisionNoTimestamp = [{
36     "buildNumber": "124",
37     "buildTime": "2015-10-27T15:34:51",
38     "revisions": {
39         "WebKit": {
40             "revision": "191622",
41         },
42     },
43     "builderName": "someBuilder",
44     "builderPassword": "somePassword",
45     "platform": "some platform",
46     "tests": {
47         "Suite": {
48             "metrics": {
49                 "Time": ["Arithmetic"],
50             },
51             "tests": {
52                 "test1": {
53                     "metrics": {"Time": { "current": [11] }},
54                 }
55             }
56         },
57     }}];
58
59 const anotherReportWithRevision = [{
60     "buildNumber": "125",
61     "buildTime": "2015-10-27T17:27:41",
62     "revisions": {
63         "WebKit": {
64             "revision": "191623",
65             "timestamp": '2015-10-27T16:38:10.768995Z',
66         },
67     },
68     "builderName": "someBuilder",
69     "builderPassword": "somePassword",
70     "platform": "some platform",
71     "tests": {
72         "Suite": {
73             "metrics": {
74                 "Time": ["Arithmetic"],
75             },
76             "tests": {
77                 "test1": {
78                     "metrics": {"Time": { "current": [12] }},
79                 }
80             }
81         },
82     }}];
83
84 const anotherReportWithRevisionNoTimestamp = [{
85     "buildNumber": "125",
86     "buildTime": "2015-10-27T17:27:41",
87     "revisions": {
88         "WebKit": {
89             "revision": "191623",
90         },
91     },
92     "builderName": "someBuilder",
93     "builderPassword": "somePassword",
94     "platform": "some platform",
95     "tests": {
96         "Suite": {
97             "metrics": {
98                 "Time": ["Arithmetic"],
99             },
100             "tests": {
101                 "test1": {
102                     "metrics": {"Time": { "current": [12] }},
103                 }
104             }
105         },
106     }}];
107
108 describe('/privileged-api/create-analysis-task with browser privileged api', function () {
109     prepareServerTest(this);
110
111     it('should return "MissingName" on an empty request', () => {
112         return PrivilegedAPI.sendRequest('create-analysis-task', {}).then((content) => {
113             assert(false, 'should never be reached');
114         }, (error) => {
115             assert.equal(error, 'MissingName');
116         });
117     });
118
119     it('should return "InvalidStartRun" when startRun is missing but endRun is set', () => {
120         return PrivilegedAPI.sendRequest('create-analysis-task', {name: 'hi', endRun: 1}).then((content) => {
121             assert(false, 'should never be reached');
122         }, (error) => {
123             assert.equal(error, 'InvalidStartRun');
124         });
125     });
126
127     it('should return "InvalidEndRun" when endRun is missing but startRun is set', () => {
128         return PrivilegedAPI.sendRequest('create-analysis-task', {name: 'hi', startRun: 1}).then((content) => {
129             assert(false, 'should never be reached');
130         }, (error) => {
131             assert.equal(error, 'InvalidEndRun');
132         });
133     });
134
135     it('should return "InvalidStartRun" when startRun is not a valid integer', () => {
136         return PrivilegedAPI.sendRequest('create-analysis-task', {name: 'hi', startRun: "foo", endRun: 1}).then((content) => {
137             assert(false, 'should never be reached');
138         }, (error) => {
139             assert.equal(error, 'InvalidStartRun');
140         });
141     });
142
143     it('should return "InvalidEndRun" when endRun is not a valid integer', () => {
144         return PrivilegedAPI.sendRequest('create-analysis-task', {name: 'hi', startRun: 1, endRun: "foo"}).then((content) => {
145             assert(false, 'should never be reached');
146         }, (error) => {
147             assert.equal(error, 'InvalidEndRun');
148         });
149     });
150
151     it('should return "InvalidStartRun" when startRun is invalid', () => {
152         return addBuilderForReport(reportWithRevision[0]).then(() => {
153             return TestServer.remoteAPI().postJSON('/api/report/', reportWithRevision);
154         }).then(() => {
155             return PrivilegedAPI.sendRequest('create-analysis-task', {name: 'hi', startRun: 100, endRun: 1}).then((content) => {
156                 assert(false, 'should never be reached');
157             }, (error) => {
158                 assert.equal(error, 'InvalidStartRun');
159             });
160         });
161     });
162
163     it('should return "InvalidEndRun" when endRun is invalid', () => {
164         return addBuilderForReport(reportWithRevision[0]).then(() => {
165             return TestServer.remoteAPI().postJSON('/api/report/', reportWithRevision);
166         }).then(() => {
167             return PrivilegedAPI.sendRequest('create-analysis-task', {name: 'hi', startRun: 1, endRun: 100}).then((content) => {
168                 assert(false, 'should never be reached');
169             }, (error) => {
170                 assert.equal(error, 'InvalidEndRun');
171             });
172         });
173     });
174
175     it('should return "InvalidTimeRange" when startRun and endRun are identical', () => {
176         return addBuilderForReport(reportWithRevision[0]).then(() => {
177             return TestServer.remoteAPI().postJSON('/api/report/', reportWithRevision);
178         }).then(() => {
179             return PrivilegedAPI.sendRequest('create-analysis-task', {name: 'hi', startRun: 1, endRun: 1}).then((content) => {
180                 assert(false, 'should never be reached');
181             }, (error) => {
182                 assert.equal(error, 'InvalidTimeRange');
183             });
184         });
185     });
186
187     it('should return "RunConfigMismatch" when startRun and endRun come from a different test configurations', () => {
188         return addBuilderForReport(reportWithRevision[0]).then(() => {
189             return TestServer.remoteAPI().postJSON('/api/report/', reportWithRevision);
190         }).then(() => {
191             return PrivilegedAPI.sendRequest('create-analysis-task', {name: 'hi', startRun: 1, endRun: 2}).then((content) => {
192                 assert(false, 'should never be reached');
193             }, (error) => {
194                 assert.equal(error, 'RunConfigMismatch');
195             });
196         });
197     });
198
199     it('should create an analysis task when name, startRun, and endRun are set properly', () => {
200         const db = TestServer.database();
201         return addBuilderForReport(reportWithRevision[0]).then(() => {
202             return TestServer.remoteAPI().postJSON('/api/report/', reportWithRevision);
203         }).then(() => {
204             return TestServer.remoteAPI().postJSON('/api/report/', anotherReportWithRevision);
205         }).then(() => {
206             return Manifest.fetch();
207         }).then(() => {
208             const test1 = Test.findByPath(['Suite', 'test1']);
209             const platform = Platform.findByName('some platform');
210             return db.selectFirstRow('test_configurations', {metric: test1.metrics()[0].id(), platform: platform.id()});
211         }).then((configRow) => {
212             return db.selectRows('test_runs', {config: configRow['id']});
213         }).then((testRuns) => {
214             assert.equal(testRuns.length, 2);
215             return PrivilegedAPI.sendRequest('create-analysis-task', {name: 'hi', startRun: testRuns[0]['id'], endRun: testRuns[1]['id']});
216         }).then((content) => {
217             return AnalysisTask.fetchById(content['taskId']);
218         }).then((task) => {
219             assert.equal(task.name(), 'hi');
220             assert(!task.hasResults());
221             assert(!task.hasPendingRequests());
222             assert.deepEqual(task.bugs(), []);
223             assert.deepEqual(task.causes(), []);
224             assert.deepEqual(task.fixes(), []);
225             assert.equal(task.changeType(), null);
226             assert.equal(task.platform().label(), 'some platform');
227             assert.equal(task.metric().test().label(), 'test1');
228         });
229     });
230
231     it('should create an analysis task and use build time as fallback when commit time is not available', () => {
232         const db = TestServer.database();
233         return addBuilderForReport(reportWithRevisionNoTimestamp[0]).then(() => {
234             return TestServer.remoteAPI().postJSON('/api/report/', reportWithRevisionNoTimestamp);
235         }).then(() => {
236             return TestServer.remoteAPI().postJSON('/api/report/', anotherReportWithRevisionNoTimestamp);
237         }).then(() => {
238             return Manifest.fetch();
239         }).then(() => {
240             const test1 = Test.findByPath(['Suite', 'test1']);
241             const platform = Platform.findByName('some platform');
242             return db.selectFirstRow('test_configurations', {metric: test1.metrics()[0].id(), platform: platform.id()});
243         }).then((configRow) => {
244             return db.selectRows('test_runs', {config: configRow['id']});
245         }).then((testRuns) => {
246             assert.equal(testRuns.length, 2);
247             return PrivilegedAPI.sendRequest('create-analysis-task', {name: 'hi', startRun: testRuns[0]['id'], endRun: testRuns[1]['id']});
248         }).then((content) => {
249             return AnalysisTask.fetchById(content['taskId']);
250         }).then((task) => {
251             assert.equal(task.name(), 'hi');
252             assert(!task.hasResults());
253             assert(!task.hasPendingRequests());
254             assert.deepEqual(task.bugs(), []);
255             assert.deepEqual(task.causes(), []);
256             assert.deepEqual(task.fixes(), []);
257             assert.equal(task.changeType(), null);
258             assert.equal(task.platform().label(), 'some platform');
259             assert.equal(task.metric().test().label(), 'test1');
260             assert.equal(task.startTime(), 1445960091000);
261             assert.equal(task.endTime(), 1445966861000);
262         });
263     });
264
265     it('should return "DuplicateAnalysisTask" when there is already an analysis task for the specified range', () => {
266         const db = TestServer.database();
267         let startId;
268         let endId;
269         return addBuilderForReport(reportWithRevision[0]).then(() => {
270             return TestServer.remoteAPI().postJSON('/api/report/', reportWithRevision);
271         }).then(() => {
272             return TestServer.remoteAPI().postJSON('/api/report/', anotherReportWithRevision);
273         }).then(() => {
274             return Manifest.fetch();
275         }).then(() => {
276             const test1 = Test.findByPath(['Suite', 'test1']);
277             const platform = Platform.findByName('some platform');
278             return db.selectFirstRow('test_configurations', {metric: test1.metrics()[0].id(), platform: platform.id()});
279         }).then((configRow) => {
280             return db.selectRows('test_runs', {config: configRow['id']});
281         }).then((testRuns) => {
282             assert.equal(testRuns.length, 2);
283             startId = testRuns[0]['id'];
284             endId = testRuns[1]['id'];
285             return PrivilegedAPI.sendRequest('create-analysis-task', {name: 'hi', startRun: startId, endRun: endId});
286         }).then((content) => {
287             return PrivilegedAPI.sendRequest('create-analysis-task', {name: 'hi', startRun: startId, endRun: endId}).then(() => {
288                 assert(false, 'should never be reached');
289             }, (error) => {
290                 assert.equal(error, 'DuplicateAnalysisTask');
291             });
292         }).then(() => {
293             return db.selectAll('analysis_tasks');
294         }).then((tasks) => {
295             assert.equal(tasks.length, 1);
296         });
297     });
298
299     it('should create an analysis task with analysis strategies when they are specified', () => {
300         const db = TestServer.database();
301         return addBuilderForReport(reportWithRevision[0]).then(() => {
302             return TestServer.remoteAPI().postJSON('/api/report/', reportWithRevision);
303         }).then(() => {
304             return TestServer.remoteAPI().postJSON('/api/report/', anotherReportWithRevision);
305         }).then(() => {
306             return Manifest.fetch();
307         }).then(() => {
308             const test1 = Test.findByPath(['Suite', 'test1']);
309             const platform = Platform.findByName('some platform');
310             return db.selectFirstRow('test_configurations', {metric: test1.metrics()[0].id(), platform: platform.id()});
311         }).then((configRow) => {
312             return db.selectRows('test_runs', {config: configRow['id']});
313         }).then((testRuns) => {
314             assert.equal(testRuns.length, 2);
315             return PrivilegedAPI.sendRequest('create-analysis-task', {
316                 name: 'hi',
317                 startRun: testRuns[0]['id'],
318                 endRun: testRuns[1]['id'],
319                 segmentationStrategy: "time series segmentation",
320                 testRangeStrategy: "student's t-test"});
321         }).then(() => {
322             return Promise.all([db.selectFirstRow('analysis_tasks'), db.selectAll('analysis_strategies')]);
323         }).then((results) => {
324             const [taskRow, strategies] = results;
325             assert(taskRow['segmentation']);
326             assert(taskRow['test_range']);
327
328             const strategyIdMap = {};
329             for (let strategy of strategies)
330                 strategyIdMap[strategy['id']] = strategy;
331
332             assert.equal(strategyIdMap[taskRow['segmentation']]['name'], "time series segmentation");
333             assert.equal(strategyIdMap[taskRow['test_range']]['name'], "student's t-test");
334         });
335     });
336
337     it('should failed with "TriggerableNotFoundForTask" when there is no matching triggerable', async () => {
338         const db = TestServer.database();
339         await addBuilderForReport(reportWithRevision[0]);
340         await TestServer.remoteAPI().postJSON('/api/report/', reportWithRevision);
341         await TestServer.remoteAPI().postJSON('/api/report/', anotherReportWithRevision);
342         await Manifest.fetch();
343
344         const test1 = Test.findByPath(['Suite', 'test1']);
345         const somePlatform = Platform.findByName('some platform');
346         const configRow = await db.selectFirstRow('test_configurations', {metric: test1.metrics()[0].id(), platform: somePlatform.id()});
347         const testRuns = await db.selectRows('test_runs', {config: configRow['id']});
348         assert.equal(testRuns.length, 2);
349
350         const webkitRepositoryRow = await db.selectFirstRow('repositories', {name: 'WebKit'});
351         const webkitId = webkitRepositoryRow.id;
352
353         const oneRevisionSet = {[webkitId]: {revision: '191622'}};
354         const anotherRevisionSet = {[webkitId]: {revision: '191623'}};
355
356         let raiseException = false;
357
358         try {
359             await PrivilegedAPI.sendRequest('create-analysis-task', {name: 'confirm', repetitionCount: 1,
360                 revisionSets: [oneRevisionSet, anotherRevisionSet],
361                 startRun: testRuns[0]['id'], endRun: testRuns[1]['id']});
362         } catch (error) {
363             assert.equal(error, 'TriggerableNotFoundForTask');
364             raiseException = true;
365         }
366         assert.ok(raiseException);
367     });
368
369     it('should create an analysis task with no test group when repetition count is 0', async () => {
370         const db = TestServer.database();
371         await addBuilderForReport(reportWithRevision[0]);
372         await TestServer.remoteAPI().postJSON('/api/report/', reportWithRevision);
373         await TestServer.remoteAPI().postJSON('/api/report/', anotherReportWithRevision);
374         await Manifest.fetch();
375
376         const test1 = Test.findByPath(['Suite', 'test1']);
377         const platform = Platform.findByName('some platform');
378         const configRow = await db.selectFirstRow('test_configurations', {metric: test1.metrics()[0].id(), platform: platform.id()});
379         const testRuns = await db.selectRows('test_runs', {config: configRow['id']});
380         assert.equal(testRuns.length, 2);
381
382         const webkitRepositoryRow = await db.selectFirstRow('repositories', {name: 'WebKit'});
383         const webkitId = webkitRepositoryRow.id;
384
385         const oneRevisionSet = {[webkitId]: {revision: '191622'}};
386         const anotherRevisionSet = {[webkitId]: {revision: '191623'}};
387
388         const content = await PrivilegedAPI.sendRequest('create-analysis-task', {name: 'confirm', repetitionCount: 0,
389             revisionSets: [oneRevisionSet, anotherRevisionSet],
390             startRun: testRuns[0]['id'], endRun: testRuns[1]['id']});
391
392         TestServer.cleanDataDirectory();
393         await Manifest.fetch();
394
395         const task = await AnalysisTask.fetchById(content['taskId']);
396         assert.equal(task.name(), 'confirm');
397         assert(!task.hasResults());
398         assert(!task.hasPendingRequests());
399         assert.deepEqual(task.bugs(), []);
400         assert.deepEqual(task.causes(), []);
401         assert.deepEqual(task.fixes(), []);
402         assert.equal(task.changeType(), null);
403         assert.equal(task.platform().label(), 'some platform');
404         assert.equal(task.metric().test().label(), 'test1');
405
406         const testGroups = await TestGroup.fetchForTask(task.id());
407         assert.equal(testGroups.length, 0);
408     });
409
410     it('should create an analysis task with test group when commit set list and a positive repetition count is specified', async () => {
411         const webkitId = 1;
412         const platformId = 1;
413         const test1Id = 2;
414         const triggerableId = 1234;
415
416         const db = TestServer.database();
417         await db.insert('tests', {id: 1, name: 'Suite'});
418         await db.insert('tests', {id: test1Id, name: 'test1', parent: 1});
419         await db.insert('repositories', {id: webkitId, name: 'WebKit'});
420         await db.insert('platforms', {id: platformId, name: 'some platform'});
421         await db.insert('build_triggerables', {id: 1234, name: 'test-triggerable'});
422         await db.insert('triggerable_repository_groups', {id: 2345, name: 'webkit-only', triggerable: triggerableId});
423         await db.insert('triggerable_repositories', {repository: webkitId, group: 2345});
424         await db.insert('triggerable_configurations', {test: test1Id, platform: platformId, triggerable: triggerableId});
425         await addBuilderForReport(reportWithRevision[0]);
426
427         await TestServer.remoteAPI().postJSON('/api/report/', reportWithRevision);
428         await TestServer.remoteAPI().postJSON('/api/report/', anotherReportWithRevision);
429         await Manifest.fetch();
430
431         let test1 = Test.findById(test1Id);
432         let somePlatform = Platform.findById(platformId);
433         const configRow = await db.selectFirstRow('test_configurations', {metric: test1.metrics()[0].id(), platform: somePlatform.id()});
434         const testRuns = await db.selectRows('test_runs', {config: configRow['id']});
435         assert.equal(testRuns.length, 2);
436
437         const oneRevisionSet = {[webkitId]: {revision: '191622'}};
438         const anotherRevisionSet = {[webkitId]: {revision: '191623'}};
439
440         const content = await PrivilegedAPI.sendRequest('create-analysis-task', {name: 'confirm', repetitionCount: 1,
441             testGroupName: 'Confirm', revisionSets: [oneRevisionSet, anotherRevisionSet],
442             startRun: testRuns[0]['id'], endRun: testRuns[1]['id']});
443
444         const task = await AnalysisTask.fetchById(content['taskId']);
445         assert.equal(task.name(), 'confirm');
446         assert(!task.hasResults());
447         assert(task.hasPendingRequests());
448         assert.deepEqual(task.bugs(), []);
449         assert.deepEqual(task.causes(), []);
450         assert.deepEqual(task.fixes(), []);
451         assert.equal(task.changeType(), null);
452         assert.equal(task.platform().label(), 'some platform');
453         assert.equal(task.metric().test().label(), 'test1');
454
455         const testGroups = await TestGroup.fetchForTask(task.id());
456         assert.equal(testGroups.length, 1);
457         const testGroup = testGroups[0];
458         assert.equal(testGroup.name(), 'Confirm');
459         const buildRequests = testGroup.buildRequests();
460         assert.equal(buildRequests.length, 2);
461
462         assert.equal(buildRequests[0].triggerable().id(), triggerableId);
463         assert.equal(buildRequests[0].triggerable().id(), triggerableId);
464
465         assert.equal(buildRequests[0].testGroup(), testGroup);
466         assert.equal(buildRequests[1].testGroup(), testGroup);
467
468         assert.equal(buildRequests[0].platform(), task.platform());
469         assert.equal(buildRequests[1].platform(), task.platform());
470
471         assert.equal(buildRequests[0].analysisTaskId(), task.id());
472         assert.equal(buildRequests[1].analysisTaskId(), task.id());
473
474         assert.equal(buildRequests[0].test(), test1);
475         assert.equal(buildRequests[1].test(), test1);
476
477         assert.ok(!buildRequests[0].isBuild());
478         assert.ok(!buildRequests[1].isBuild());
479         assert.ok(buildRequests[0].isTest());
480         assert.ok(buildRequests[1].isTest());
481
482         const firstCommitSet = buildRequests[0].commitSet();
483         const secondCommitSet = buildRequests[1].commitSet();
484         const webkitRepository = Repository.findById(webkitId);
485         assert.equal(firstCommitSet.commitForRepository(webkitRepository).revision(), '191622');
486         assert.equal(secondCommitSet.commitForRepository(webkitRepository).revision(), '191623');
487     });
488 });
489
490 describe('/privileged-api/create-analysis-task with node privileged api', function () {
491     prepareServerTest(this, 'node');
492     beforeEach(() => {
493         PrivilegedAPI.configure('test', 'password');
494     });
495
496     it('should return "SlaveNotFound" when incorrect slave user and password combination is provided and no analysis task, test group or build request should be created', async () => {
497         PrivilegedAPI.configure('test', 'wrongpassword');
498         const db = TestServer.database();
499         await addBuilderForReport(reportWithRevision[0]);
500         await TestServer.remoteAPI().postJSON('/api/report/', reportWithRevision);
501         await TestServer.remoteAPI().postJSON('/api/report/', anotherReportWithRevision);
502         await Manifest.fetch();
503
504         const test1 = Test.findByPath(['Suite', 'test1']);
505         const somePlatform = Platform.findByName('some platform');
506         const configRow = await db.selectFirstRow('test_configurations', {metric: test1.metrics()[0].id(), platform: somePlatform.id()});
507         const testRuns = await db.selectRows('test_runs', {config: configRow['id']});
508         assert.equal(testRuns.length, 2);
509
510         const webkitRepositoryRow = await db.selectFirstRow('repositories', {name: 'WebKit'});
511         const webkitId = webkitRepositoryRow.id;
512
513         const oneRevisionSet = {[webkitId]: {revision: '191622'}};
514         const anotherRevisionSet = {[webkitId]: {revision: '191623'}};
515
516         let raiseException = false;
517
518         try {
519             await PrivilegedAPI.sendRequest('create-analysis-task', {name: 'confirm', repetitionCount: 1,
520                 revisionSets: [oneRevisionSet, anotherRevisionSet],
521                 startRun: testRuns[0]['id'], endRun: testRuns[1]['id']});
522         } catch (error) {
523             assert.equal(error, 'SlaveNotFound');
524             raiseException = true;
525         }
526         assert.ok(raiseException);
527
528         const allAnalysisTasks = await db.selectRows('analysis_tasks');
529         assert.ok(!allAnalysisTasks.length);
530
531         const allTestGroups = await db.selectRows('analysis_test_groups');
532         assert.ok(!allTestGroups.length);
533
534         const allBuildRequests = await db.selectRows('build_requests');
535         assert.ok(!allBuildRequests.length);
536     });
537
538     it('should create an analysis task with test group when commit set list and a positive repetition count is specified', async () => {
539         const webkitId = 1;
540         const platformId = 1;
541         const test1Id = 2;
542         const triggerableId = 1234;
543
544         const db = TestServer.database();
545         await db.insert('tests', {id: 1, name: 'Suite'});
546         await db.insert('tests', {id: test1Id, name: 'test1', parent: 1});
547         await db.insert('repositories', {id: webkitId, name: 'WebKit'});
548         await db.insert('platforms', {id: platformId, name: 'some platform'});
549         await db.insert('build_triggerables', {id: 1234, name: 'test-triggerable'});
550         await db.insert('triggerable_repository_groups', {id: 2345, name: 'webkit-only', triggerable: triggerableId});
551         await db.insert('triggerable_repositories', {repository: webkitId, group: 2345});
552         await db.insert('triggerable_configurations', {test: test1Id, platform: platformId, triggerable: triggerableId});
553         await addBuilderForReport(reportWithRevision[0]);
554
555         await TestServer.remoteAPI().postJSON('/api/report/', reportWithRevision);
556         await TestServer.remoteAPI().postJSON('/api/report/', anotherReportWithRevision);
557         await Manifest.fetch();
558
559         let test1 = Test.findById(test1Id);
560         let somePlatform = Platform.findById(platformId);
561         const configRow = await db.selectFirstRow('test_configurations', {metric: test1.metrics()[0].id(), platform: somePlatform.id()});
562         const testRuns = await db.selectRows('test_runs', {config: configRow['id']});
563         assert.equal(testRuns.length, 2);
564
565         const oneRevisionSet = {[webkitId]: {revision: '191622'}};
566         const anotherRevisionSet = {[webkitId]: {revision: '191623'}};
567
568         const content = await PrivilegedAPI.sendRequest('create-analysis-task', {name: 'confirm', repetitionCount: 1,
569             testGroupName: 'Confirm', revisionSets: [oneRevisionSet, anotherRevisionSet],
570             startRun: testRuns[0]['id'], endRun: testRuns[1]['id']});
571
572         const task = await AnalysisTask.fetchById(content['taskId']);
573         assert.equal(task.name(), 'confirm');
574         assert(!task.hasResults());
575         assert(task.hasPendingRequests());
576         assert.deepEqual(task.bugs(), []);
577         assert.deepEqual(task.causes(), []);
578         assert.deepEqual(task.fixes(), []);
579         assert.equal(task.changeType(), null);
580         assert.equal(task.platform().label(), 'some platform');
581         assert.equal(task.metric().test().label(), 'test1');
582
583         const testGroups = await TestGroup.fetchForTask(task.id());
584         assert.equal(testGroups.length, 1);
585         const testGroup = testGroups[0];
586         assert.equal(testGroup.name(), 'Confirm');
587         const buildRequests = testGroup.buildRequests();
588         assert.equal(buildRequests.length, 2);
589
590         assert.equal(buildRequests[0].triggerable().id(), triggerableId);
591         assert.equal(buildRequests[0].triggerable().id(), triggerableId);
592
593         assert.equal(buildRequests[0].testGroup(), testGroup);
594         assert.equal(buildRequests[1].testGroup(), testGroup);
595
596         assert.equal(buildRequests[0].platform(), task.platform());
597         assert.equal(buildRequests[1].platform(), task.platform());
598
599         assert.equal(buildRequests[0].analysisTaskId(), task.id());
600         assert.equal(buildRequests[1].analysisTaskId(), task.id());
601
602         assert.equal(buildRequests[0].test(), test1);
603         assert.equal(buildRequests[1].test(), test1);
604
605         assert.ok(!buildRequests[0].isBuild());
606         assert.ok(!buildRequests[1].isBuild());
607         assert.ok(buildRequests[0].isTest());
608         assert.ok(buildRequests[1].isTest());
609
610         const firstCommitSet = buildRequests[0].commitSet();
611         const secondCommitSet = buildRequests[1].commitSet();
612         const webkitRepository = Repository.findById(webkitId);
613         assert.equal(firstCommitSet.commitForRepository(webkitRepository).revision(), '191622');
614         assert.equal(secondCommitSet.commitForRepository(webkitRepository).revision(), '191623');
615     });
616 });