8775c5554ac297d3b3866186e9bbd9bd4d418d83
[WebKit.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 anotherReportWithRevision = [{
36     "buildNumber": "125",
37     "buildTime": "2015-10-27T17:27:41",
38     "revisions": {
39         "WebKit": {
40             "revision": "191623",
41             "timestamp": '2015-10-27T16:38:10.768995Z',
42         },
43     },
44     "builderName": "someBuilder",
45     "builderPassword": "somePassword",
46     "platform": "some platform",
47     "tests": {
48         "Suite": {
49             "metrics": {
50                 "Time": ["Arithmetic"],
51             },
52             "tests": {
53                 "test1": {
54                     "metrics": {"Time": { "current": [12] }},
55                 }
56             }
57         },
58     }}];
59
60 describe('/privileged-api/create-analysis-task', function () {
61     prepareServerTest(this);
62
63     it('should return "MissingName" on an empty request', () => {
64         return PrivilegedAPI.sendRequest('create-analysis-task', {}).then((content) => {
65             assert(false, 'should never be reached');
66         }, (error) => {
67             assert.equal(error, 'MissingName');
68         });
69     });
70
71     it('should return "InvalidStartRun" when startRun is missing but endRun is set', () => {
72         return PrivilegedAPI.sendRequest('create-analysis-task', {name: 'hi', endRun: 1}).then((content) => {
73             assert(false, 'should never be reached');
74         }, (error) => {
75             assert.equal(error, 'InvalidStartRun');
76         });
77     });
78
79     it('should return "InvalidEndRun" when endRun is missing but startRun is set', () => {
80         return PrivilegedAPI.sendRequest('create-analysis-task', {name: 'hi', startRun: 1}).then((content) => {
81             assert(false, 'should never be reached');
82         }, (error) => {
83             assert.equal(error, 'InvalidEndRun');
84         });
85     });
86
87     it('should return "InvalidStartRun" when startRun is not a valid integer', () => {
88         return PrivilegedAPI.sendRequest('create-analysis-task', {name: 'hi', startRun: "foo", endRun: 1}).then((content) => {
89             assert(false, 'should never be reached');
90         }, (error) => {
91             assert.equal(error, 'InvalidStartRun');
92         });
93     });
94
95     it('should return "InvalidEndRun" when endRun is not a valid integer', () => {
96         return PrivilegedAPI.sendRequest('create-analysis-task', {name: 'hi', startRun: 1, endRun: "foo"}).then((content) => {
97             assert(false, 'should never be reached');
98         }, (error) => {
99             assert.equal(error, 'InvalidEndRun');
100         });
101     });
102
103     it('should return "InvalidStartRun" when startRun is invalid', () => {
104         return addBuilderForReport(reportWithRevision[0]).then(() => {
105             return TestServer.remoteAPI().postJSON('/api/report/', reportWithRevision);
106         }).then(() => {
107             return PrivilegedAPI.sendRequest('create-analysis-task', {name: 'hi', startRun: 100, endRun: 1}).then((content) => {
108                 assert(false, 'should never be reached');
109             }, (error) => {
110                 assert.equal(error, 'InvalidStartRun');
111             });
112         });
113     });
114
115     it('should return "InvalidEndRun" when endRun is invalid', () => {
116         return addBuilderForReport(reportWithRevision[0]).then(() => {
117             return TestServer.remoteAPI().postJSON('/api/report/', reportWithRevision);
118         }).then(() => {
119             return PrivilegedAPI.sendRequest('create-analysis-task', {name: 'hi', startRun: 1, endRun: 100}).then((content) => {
120                 assert(false, 'should never be reached');
121             }, (error) => {
122                 assert.equal(error, 'InvalidEndRun');
123             });
124         });
125     });
126
127     it('should return "InvalidTimeRange" when startRun and endRun are identical', () => {
128         return addBuilderForReport(reportWithRevision[0]).then(() => {
129             return TestServer.remoteAPI().postJSON('/api/report/', reportWithRevision);
130         }).then(() => {
131             return PrivilegedAPI.sendRequest('create-analysis-task', {name: 'hi', startRun: 1, endRun: 1}).then((content) => {
132                 assert(false, 'should never be reached');
133             }, (error) => {
134                 assert.equal(error, 'InvalidTimeRange');
135             });
136         });
137     });
138
139     it('should return "RunConfigMismatch" when startRun and endRun come from a different test configurations', () => {
140         return addBuilderForReport(reportWithRevision[0]).then(() => {
141             return TestServer.remoteAPI().postJSON('/api/report/', reportWithRevision);
142         }).then(() => {
143             return PrivilegedAPI.sendRequest('create-analysis-task', {name: 'hi', startRun: 1, endRun: 2}).then((content) => {
144                 assert(false, 'should never be reached');
145             }, (error) => {
146                 assert.equal(error, 'RunConfigMismatch');
147             });
148         });
149     });
150
151     it('should create an analysis task when name, startRun, and endRun are set properly', () => {
152         const db = TestServer.database();
153         return addBuilderForReport(reportWithRevision[0]).then(() => {
154             return TestServer.remoteAPI().postJSON('/api/report/', reportWithRevision);
155         }).then(() => {
156             return TestServer.remoteAPI().postJSON('/api/report/', anotherReportWithRevision);
157         }).then(() => {
158             return Manifest.fetch();
159         }).then(() => {
160             const test1 = Test.findByPath(['Suite', 'test1']);
161             const platform = Platform.findByName('some platform');
162             return db.selectFirstRow('test_configurations', {metric: test1.metrics()[0].id(), platform: platform.id()});
163         }).then((configRow) => {
164             return db.selectRows('test_runs', {config: configRow['id']});
165         }).then((testRuns) => {
166             assert.equal(testRuns.length, 2);
167             return PrivilegedAPI.sendRequest('create-analysis-task', {name: 'hi', startRun: testRuns[0]['id'], endRun: testRuns[1]['id']});
168         }).then((content) => {
169             return AnalysisTask.fetchById(content['taskId']);
170         }).then((task) => {
171             assert.equal(task.name(), 'hi');
172             assert(!task.hasResults());
173             assert(!task.hasPendingRequests());
174             assert.deepEqual(task.bugs(), []);
175             assert.deepEqual(task.causes(), []);
176             assert.deepEqual(task.fixes(), []);
177             assert.equal(task.changeType(), null);
178             assert.equal(task.platform().label(), 'some platform');
179             assert.equal(task.metric().test().label(), 'test1');
180         });
181     });
182
183     it('should return "DuplicateAnalysisTask" when there is already an analysis task for the specified range', () => {
184         const db = TestServer.database();
185         let startId;
186         let endId;
187         return addBuilderForReport(reportWithRevision[0]).then(() => {
188             return TestServer.remoteAPI().postJSON('/api/report/', reportWithRevision);
189         }).then(() => {
190             return TestServer.remoteAPI().postJSON('/api/report/', anotherReportWithRevision);
191         }).then(() => {
192             return Manifest.fetch();
193         }).then(() => {
194             const test1 = Test.findByPath(['Suite', 'test1']);
195             const platform = Platform.findByName('some platform');
196             return db.selectFirstRow('test_configurations', {metric: test1.metrics()[0].id(), platform: platform.id()});
197         }).then((configRow) => {
198             return db.selectRows('test_runs', {config: configRow['id']});
199         }).then((testRuns) => {
200             assert.equal(testRuns.length, 2);
201             startId = testRuns[0]['id'];
202             endId = testRuns[1]['id'];
203             return PrivilegedAPI.sendRequest('create-analysis-task', {name: 'hi', startRun: startId, endRun: endId});
204         }).then((content) => {
205             return PrivilegedAPI.sendRequest('create-analysis-task', {name: 'hi', startRun: startId, endRun: endId}).then(() => {
206                 assert(false, 'should never be reached');
207             }, (error) => {
208                 assert.equal(error, 'DuplicateAnalysisTask');
209             });
210         }).then(() => {
211             return db.selectAll('analysis_tasks');
212         }).then((tasks) => {
213             assert.equal(tasks.length, 1);
214         });
215     });
216
217     it('should create an analysis task with analysis strategies when they are specified', () => {
218         const db = TestServer.database();
219         return addBuilderForReport(reportWithRevision[0]).then(() => {
220             return TestServer.remoteAPI().postJSON('/api/report/', reportWithRevision);
221         }).then(() => {
222             return TestServer.remoteAPI().postJSON('/api/report/', anotherReportWithRevision);
223         }).then(() => {
224             return Manifest.fetch();
225         }).then(() => {
226             const test1 = Test.findByPath(['Suite', 'test1']);
227             const platform = Platform.findByName('some platform');
228             return db.selectFirstRow('test_configurations', {metric: test1.metrics()[0].id(), platform: platform.id()});
229         }).then((configRow) => {
230             return db.selectRows('test_runs', {config: configRow['id']});
231         }).then((testRuns) => {
232             assert.equal(testRuns.length, 2);
233             return PrivilegedAPI.sendRequest('create-analysis-task', {
234                 name: 'hi',
235                 startRun: testRuns[0]['id'],
236                 endRun: testRuns[1]['id'],
237                 segmentationStrategy: "time series segmentation",
238                 testRangeStrategy: "student's t-test"});
239         }).then(() => {
240             return Promise.all([db.selectFirstRow('analysis_tasks'), db.selectAll('analysis_strategies')]);
241         }).then((results) => {
242             const [taskRow, strategies] = results;
243             assert(taskRow['segmentation']);
244             assert(taskRow['test_range']);
245
246             const strategyIdMap = {};
247             for (let strategy of strategies)
248                 strategyIdMap[strategy['id']] = strategy;
249
250             assert.equal(strategyIdMap[taskRow['segmentation']]['name'], "time series segmentation");
251             assert.equal(strategyIdMap[taskRow['test_range']]['name'], "student's t-test");
252         });
253     });
254
255 });