Add the UI for scheduling a A/B testing with a custom root
[WebKit-https.git] / Websites / perf.webkit.org / server-tests / privileged-api-create-test-group-tests.js
1 'use strict';
2
3 const assert = require('assert');
4
5 const MockData = require('./resources/mock-data.js');
6 const TestServer = require('./resources/test-server.js');
7 const TemporaryFile = require('./resources/temporary-file.js').TemporaryFile;
8 const addSlaveForReport = require('./resources/common-operations.js').addSlaveForReport;
9 const prepareServerTest = require('./resources/common-operations.js').prepareServerTest;
10
11 function createAnalysisTask(name)
12 {
13     const reportWithRevision = [{
14         "buildNumber": "124",
15         "buildTime": "2015-10-27T15:34:51",
16         "revisions": {
17             "WebKit": {
18                 "revision": "191622",
19                 "timestamp": '2015-10-27T11:36:56.878473Z',
20             },
21             "macOS": {
22                 "revision": "15A284",
23             }
24         },
25         "builderName": "someBuilder",
26         "slaveName": "someSlave",
27         "slavePassword": "somePassword",
28         "platform": "some platform",
29         "tests": {
30             "some test": {
31                 "metrics": {
32                     "Time": ["Arithmetic"],
33                 },
34                 "tests": {
35                     "test1": {
36                         "metrics": {"Time": { "current": [11] }},
37                     }
38                 }
39             },
40         }}];
41
42     const anotherReportWithRevision = [{
43         "buildNumber": "125",
44         "buildTime": "2015-10-27T17:27:41",
45         "revisions": {
46             "WebKit": {
47                 "revision": "191623",
48                 "timestamp": '2015-10-27T16:38:10.768995Z',
49             },
50             "macOS": {
51                 "revision": "15A284",
52             }
53         },
54         "builderName": "someBuilder",
55         "slaveName": "someSlave",
56         "slavePassword": "somePassword",
57         "platform": "some platform",
58         "tests": {
59             "some test": {
60                 "metrics": {
61                     "Time": ["Arithmetic"],
62                 },
63                 "tests": {
64                     "test1": {
65                         "metrics": {"Time": { "current": [12] }},
66                     }
67                 }
68             },
69         }}];
70
71     const db = TestServer.database();
72     const remote = TestServer.remoteAPI();
73     return addSlaveForReport(reportWithRevision[0]).then(() => {
74         return remote.postJSON('/api/report/', reportWithRevision);
75     }).then(() => {
76         return remote.postJSON('/api/report/', anotherReportWithRevision);
77     }).then((result) => {
78         return Manifest.fetch();
79     }).then(() => {
80         const test = Test.findByPath(['some test', 'test1']);
81         const platform = Platform.findByName('some platform');
82         return db.selectFirstRow('test_configurations', {metric: test.metrics()[0].id(), platform: platform.id()});
83     }).then((configRow) => {
84         return db.selectRows('test_runs', {config: configRow['id']});
85     }).then((testRuns) => {
86         assert.equal(testRuns.length, 2);
87         return PrivilegedAPI.sendRequest('create-analysis-task', {
88             name: name,
89             startRun: testRuns[0]['id'],
90             endRun: testRuns[1]['id'],
91         });
92     }).then((content) => content['taskId']);
93 }
94
95 function addTriggerableAndCreateTask(name)
96 {
97     const report = {
98         'slaveName': 'anotherSlave',
99         'slavePassword': 'anotherPassword',
100         'triggerable': 'build-webkit',
101         'configurations': [
102             {test: MockData.someTestId(), platform: MockData.somePlatformId()}
103         ],
104         'repositoryGroups': [
105             {name: 'webkit-only', repositories: [MockData.webkitRepositoryId()]},
106             {name: 'system-and-webkit', repositories: [MockData.macosRepositoryId(), MockData.webkitRepositoryId()]},
107         ]
108     };
109     return MockData.addMockData(TestServer.database()).then(() => {
110         return addSlaveForReport(report);
111     }).then(() => {
112         return TestServer.remoteAPI().postJSON('/api/update-triggerable/', report);
113     }).then(() => {
114         return createAnalysisTask(name);
115     });
116 }
117
118 describe('/privileged-api/create-test-group', function () {
119     prepareServerTest(this);
120     TemporaryFile.inject();
121
122     it('should return "InvalidName" on an empty request', () => {
123         return PrivilegedAPI.sendRequest('create-test-group', {}).then((content) => {
124             assert(false, 'should never be reached');
125         }, (error) => {
126             assert.equal(error, 'InvalidName');
127         });
128     });
129
130     it('should return "InvalidTask" when task is not specified', () => {
131         return PrivilegedAPI.sendRequest('create-test-group', {name: 'test', commitSets: [[1]]}).then((content) => {
132             assert(false, 'should never be reached');
133         }, (error) => {
134             assert.equal(error, 'InvalidTask');
135         });
136     });
137
138     it('should return "InvalidTask" when task is not a valid integer', () => {
139         return PrivilegedAPI.sendRequest('create-test-group', {name: 'test', task: 'foo', commitSets: [[1]]}).then((content) => {
140             assert(false, 'should never be reached');
141         }, (error) => {
142             assert.equal(error, 'InvalidTask');
143         });
144     });
145
146     it('should return "InvalidCommitSets" when commit sets are not specified', () => {
147         return PrivilegedAPI.sendRequest('create-test-group', {name: 'test', task: 1, repetitionCount: 1}).then((content) => {
148             assert(false, 'should never be reached');
149         }, (error) => {
150             assert.equal(error, 'InvalidCommitSets');
151         });
152     });
153
154     it('should return "InvalidCommitSets" when commit sets is empty', () => {
155         return PrivilegedAPI.sendRequest('create-test-group', {name: 'test', task: 1, repetitionCount: 1, commitSets: {}}).then((content) => {
156             assert(false, 'should never be reached');
157         }, (error) => {
158             assert.equal(error, 'InvalidCommitSets');
159         });
160     });
161
162     it('should return "InvalidTask" when there is no matching task', () => {
163         return PrivilegedAPI.sendRequest('create-test-group', {name: 'test', task: 1, repetitionCount: 1, commitSets: {'WebKit': []}}).then((content) => {
164             assert(false, 'should never be reached');
165         }, (error) => {
166             assert.equal(error, 'InvalidTask');
167         });
168     });
169
170     it('should return "InvalidRepetitionCount" when repetitionCount is not a valid integer', () => {
171         return PrivilegedAPI.sendRequest('create-test-group', {name: 'test', task: 1, repetitionCount: 'foo', commitSets: {'WebKit': []}}).then((content) => {
172             assert(false, 'should never be reached');
173         }, (error) => {
174             assert.equal(error, 'InvalidRepetitionCount');
175         });
176     });
177
178     it('should return "InvalidRepetitionCount" when repetitionCount is a negative integer', () => {
179         return PrivilegedAPI.sendRequest('create-test-group', {name: 'test', task: 1, repetitionCount: -5, commitSets: {'WebKit': []}}).then((content) => {
180             assert(false, 'should never be reached');
181         }, (error) => {
182             assert.equal(error, 'InvalidRepetitionCount');
183         });
184     });
185
186     it('should return "InvalidTask" when there is no matching task', () => {
187         return PrivilegedAPI.sendRequest('create-test-group', {name: 'test', task: 1, commitSets: {'WebKit': []}}).then((content) => {
188             assert(false, 'should never be reached');
189         }, (error) => {
190             assert.equal(error, 'InvalidTask');
191         });
192     });
193
194     it('should return "TriggerableNotFoundForTask" when there is no matching triggerable', () => {
195         return createAnalysisTask('some task').then((taskId) => {
196             return PrivilegedAPI.sendRequest('create-test-group', {name: 'test', task: taskId, commitSets: {'WebKit': []}}).then((content) => {
197                 assert(false, 'should never be reached');
198             }, (error) => {
199                 assert.equal(error, 'TriggerableNotFoundForTask');
200             });
201         });
202     });
203
204     it('should return "InvalidCommitSets" when each repository specifies zero revisions', () => {
205         return addTriggerableAndCreateTask('some task').then((taskId) => {
206             return PrivilegedAPI.sendRequest('create-test-group', {name: 'test', task: taskId, commitSets: {'WebKit': []}}).then((content) => {
207                 assert(false, 'should never be reached');
208             }, (error) => {
209                 assert.equal(error, 'InvalidCommitSets');
210             });
211         });
212     });
213
214     it('should return "InvalidRevisionSets" when a revision set is empty', () => {
215         return addTriggerableAndCreateTask('some task').then((taskId) => {
216             const webkit = Repository.all().find((repository) => repository.name() == 'WebKit');
217             return PrivilegedAPI.sendRequest('create-test-group', {name: 'test', task: taskId, revisionSets: [{[webkit.id()]: '191622'}, {}]}).then((content) => {
218                 assert(false, 'should never be reached');
219             }, (error) => {
220                 assert.equal(error, 'InvalidRevisionSets');
221             });
222         });
223     });
224
225     it('should return "InvalidRevisionSets" when the number of revision sets is less than two', () => {
226         return addTriggerableAndCreateTask('some task').then((taskId) => {
227             const webkit = Repository.all().find((repository) => repository.name() == 'WebKit');
228             return PrivilegedAPI.sendRequest('create-test-group', {name: 'test', task: taskId, revisionSets: [{[webkit.id()]: '191622'}]}).then((content) => {
229                 assert(false, 'should never be reached');
230             }, (error) => {
231                 assert.equal(error, 'InvalidRevisionSets');
232             });
233         });
234     });
235
236     it('should return "RepositoryNotFound" when commit sets contains an invalid repository', () => {
237         return addTriggerableAndCreateTask('some task').then((taskId) => {
238             return PrivilegedAPI.sendRequest('create-test-group', {name: 'test', task: taskId, commitSets: {'Foo': []}}).then((content) => {
239                 assert(false, 'should never be reached');
240             }, (error) => {
241                 assert.equal(error, 'RepositoryNotFound');
242             });
243         });
244     });
245
246     it('should return "RevisionNotFound" when commit sets contains an invalid revision', () => {
247         return addTriggerableAndCreateTask('some task').then((taskId) => {
248             return PrivilegedAPI.sendRequest('create-test-group', {name: 'test', task: taskId, commitSets: {'WebKit': ['1']}}).then((content) => {
249                 assert(false, 'should never be reached');
250             }, (error) => {
251                 assert.equal(error, 'RevisionNotFound');
252             });
253         });
254     });
255
256     it('should return "RevisionNotFound" when revision sets contains an invalid revision', () => {
257         return addTriggerableAndCreateTask('some task').then((taskId) => {
258             const webkit = Repository.all().find((repository) => repository.name() == 'WebKit');
259             return PrivilegedAPI.sendRequest('create-test-group', {name: 'test', task: taskId, revisionSets: [{[webkit.id()]: '191622'}, {[webkit.id()]: '1'}]}).then((content) => {
260                 assert(false, 'should never be reached');
261             }, (error) => {
262                 assert.equal(error, 'RevisionNotFound');
263             });
264         });
265     });
266
267     it('should return "InvalidUploadedFile" when revision sets contains an invalid file ID', () => {
268         return addTriggerableAndCreateTask('some task').then((taskId) => {
269             const webkit = Repository.all().find((repository) => repository.name() == 'WebKit');
270             const revisionSets = [{[webkit.id()]: '191622', 'customRoots': ['1']}, {[webkit.id()]: '1'}];
271             return PrivilegedAPI.sendRequest('create-test-group', {name: 'test', task: taskId, revisionSets}).then((content) => {
272                 assert(false, 'should never be reached');
273             }, (error) => {
274                 assert.equal(error, 'InvalidUploadedFile');
275             });
276         });
277     });
278
279     it('should return "InvalidRepository" when a revision set uses a repository name instead of a repository id', () => {
280         return addTriggerableAndCreateTask('some task').then((taskId) => {
281             return PrivilegedAPI.sendRequest('create-test-group', {name: 'test', task: taskId, revisionSets: [{'WebKit': '191622'}, {}]}).then((content) => {
282                 assert(false, 'should never be reached');
283             }, (error) => {
284                 assert.equal(error, 'InvalidRepository');
285             });
286         });
287     });
288
289     it('should return "InvalidCommitSets" when commit sets contains an inconsistent number of revisions', () => {
290         return addTriggerableAndCreateTask('some task').then((taskId) => {
291             return PrivilegedAPI.sendRequest('create-test-group', {name: 'test', task: taskId, commitSets: {'WebKit': ['191622', '191623'], 'macOS': ['15A284']}}).then((content) => {
292                 assert(false, 'should never be reached');
293             }, (error) => {
294                 assert.equal(error, 'InvalidCommitSets');
295             });
296         });
297     });
298
299     it('should create a test group from commitSets with the repetition count of one when repetitionCount is omitted', () => {
300         return addTriggerableAndCreateTask('some task').then((taskId) => {
301             let insertedGroupId;
302             return PrivilegedAPI.sendRequest('create-test-group', {name: 'test', task: taskId, commitSets: {'macOS': ['15A284', '15A284'], 'WebKit': ['191622', '191623']}}).then((content) => {
303                 insertedGroupId = content['testGroupId'];
304                 return TestGroup.fetchByTask(taskId);
305             }).then((testGroups) => {
306                 assert.equal(testGroups.length, 1);
307                 const group = testGroups[0];
308                 assert.equal(group.id(), insertedGroupId);
309                 assert.equal(group.repetitionCount(), 1);
310                 const requests = group.buildRequests();
311                 assert.equal(requests.length, 2);
312
313                 const macos = Repository.findById(MockData.macosRepositoryId());
314                 const webkit = Repository.findById(MockData.webkitRepositoryId());
315                 const set0 = requests[0].commitSet();
316                 const set1 = requests[1].commitSet();
317                 assert.deepEqual(Repository.sortByNamePreferringOnesWithURL(set0.repositories()), [webkit, macos]);
318                 assert.deepEqual(Repository.sortByNamePreferringOnesWithURL(set1.repositories()), [webkit, macos]);
319                 assert.equal(set0.revisionForRepository(macos), '15A284');
320                 assert.equal(set0.revisionForRepository(webkit), '191622');
321                 assert.equal(set1.revisionForRepository(macos), '15A284');
322                 assert.equal(set1.revisionForRepository(webkit), '191623');
323
324                 const repositoryGroup = requests[0].repositoryGroup();
325                 assert.equal(repositoryGroup.name(), 'system-and-webkit');
326                 assert.equal(requests[1].repositoryGroup(), repositoryGroup);
327                 assert(repositoryGroup.accepts(set0));
328                 assert(repositoryGroup.accepts(set1));
329             });
330         });
331     });
332
333     it('should create a test group from revisionSets with the repetition count of one when repetitionCount is omitted', () => {
334         let webkit;
335         return addTriggerableAndCreateTask('some task').then((taskId) => {
336             const webkit = Repository.findById(MockData.webkitRepositoryId());
337             const params = {name: 'test', task: taskId, revisionSets: [{[webkit.id()]: '191622'}, {[webkit.id()]: '191623'}]};
338             let insertedGroupId;
339             return PrivilegedAPI.sendRequest('create-test-group', params).then((content) => {
340                 insertedGroupId = content['testGroupId'];
341                 return TestGroup.fetchByTask(taskId);
342             }).then((testGroups) => {
343                 assert.equal(testGroups.length, 1);
344                 const group = testGroups[0];
345                 assert.equal(group.id(), insertedGroupId);
346                 assert.equal(group.repetitionCount(), 1);
347                 const requests = group.buildRequests();
348                 assert.equal(requests.length, 2);
349
350                 const set0 = requests[0].commitSet();
351                 const set1 = requests[1].commitSet();
352                 assert.deepEqual(set0.repositories(), [webkit]);
353                 assert.deepEqual(set1.repositories(), [webkit]);
354                 assert.equal(set0.revisionForRepository(webkit), '191622');
355                 assert.equal(set1.revisionForRepository(webkit), '191623');
356
357                 const repositoryGroup = requests[0].repositoryGroup();
358                 assert.equal(repositoryGroup.name(), 'webkit-only');
359                 assert.equal(repositoryGroup, requests[1].repositoryGroup());
360                 assert(repositoryGroup.accepts(set0));
361                 assert(repositoryGroup.accepts(set1));
362             });
363         });
364     });
365
366     it('should create a test group with the repetition count of two with two repositories', () => {
367         return addTriggerableAndCreateTask('some task').then((taskId) => {
368             let insertedGroupId;
369             return PrivilegedAPI.sendRequest('create-test-group', {name: 'test', task: taskId, repetitionCount: 2,
370                 commitSets: {'WebKit': ['191622', '191623'], 'macOS': ['15A284', '15A284']}}).then((content) => {
371                 insertedGroupId = content['testGroupId'];
372                 return TestGroup.fetchByTask(taskId);
373             }).then((testGroups) => {
374                 assert.equal(testGroups.length, 1);
375                 const group = testGroups[0];
376                 assert.equal(group.id(), insertedGroupId);
377                 assert.equal(group.repetitionCount(), 2);
378                 const requests = group.buildRequests();
379                 assert.equal(requests.length, 4);
380                 const webkit = Repository.all().filter((repository) => repository.name() == 'WebKit')[0];
381                 const macos = Repository.all().filter((repository) => repository.name() == 'macOS')[0];
382
383                 const set0 = requests[0].commitSet();
384                 const set1 = requests[1].commitSet();
385                 assert.equal(requests[2].commitSet(), set0);
386                 assert.equal(requests[3].commitSet(), set1);
387                 assert.deepEqual(Repository.sortByNamePreferringOnesWithURL(set0.repositories()), [webkit, macos]);
388                 assert.deepEqual(Repository.sortByNamePreferringOnesWithURL(set1.repositories()), [webkit, macos]);
389                 assert.equal(set0.revisionForRepository(webkit), '191622');
390                 assert.equal(set0.revisionForRepository(macos), '15A284');
391                 assert.equal(set1.revisionForRepository(webkit), '191623');
392                 assert.equal(set1.revisionForRepository(macos), '15A284');
393                 assert.equal(set0.commitForRepository(macos), set1.commitForRepository(macos));
394
395                 const repositoryGroup = requests[0].repositoryGroup();
396                 assert.equal(repositoryGroup.name(), 'system-and-webkit');
397                 assert.equal(requests[1].repositoryGroup(), repositoryGroup);
398                 assert.equal(requests[2].repositoryGroup(), repositoryGroup);
399                 assert.equal(requests[3].repositoryGroup(), repositoryGroup);
400                 assert(repositoryGroup.accepts(set0));
401                 assert(repositoryGroup.accepts(set1));
402             });
403         });
404     });
405
406     it('should create a test group using different repository groups if needed', () => {
407         let webkit;
408         let macos;
409         return addTriggerableAndCreateTask('some task').then((taskId) => {
410             webkit = Repository.findById(MockData.webkitRepositoryId());
411             macos = Repository.findById(MockData.macosRepositoryId());
412             const params = {name: 'test', task: taskId, repetitionCount: 2,
413                 revisionSets: [{[macos.id()]: '15A284', [webkit.id()]: '191622'}, {[webkit.id()]: '191623'}]};
414             let insertedGroupId;
415             return PrivilegedAPI.sendRequest('create-test-group', params).then((content) => {
416                 insertedGroupId = content['testGroupId'];
417                 return TestGroup.fetchByTask(taskId);
418             }).then((testGroups) => {
419                 assert.equal(testGroups.length, 1);
420                 const group = testGroups[0];
421                 assert.equal(group.id(), insertedGroupId);
422                 assert.equal(group.repetitionCount(), 2);
423                 const requests = group.buildRequests();
424                 assert.equal(requests.length, 4);
425
426                 const set0 = requests[0].commitSet();
427                 const set1 = requests[1].commitSet();
428                 assert.deepEqual(Repository.sortByNamePreferringOnesWithURL(set0.repositories()), [webkit, macos]);
429                 assert.deepEqual(set1.repositories(), [webkit]);
430                 assert.equal(set0.revisionForRepository(webkit), '191622');
431                 assert.equal(set0.revisionForRepository(macos), '15A284');
432                 assert.equal(set1.revisionForRepository(webkit), '191623');
433                 assert.equal(set1.revisionForRepository(macos), null);
434
435                 const repositoryGroup0 = requests[0].repositoryGroup();
436                 assert.equal(repositoryGroup0.name(), 'system-and-webkit');
437                 assert.equal(repositoryGroup0, requests[2].repositoryGroup());
438                 assert(repositoryGroup0.accepts(set0));
439                 assert(!repositoryGroup0.accepts(set1));
440
441                 const repositoryGroup1 = requests[1].repositoryGroup();
442                 assert.equal(repositoryGroup1.name(), 'webkit-only');
443                 assert.equal(repositoryGroup1, requests[3].repositoryGroup());
444                 assert(!repositoryGroup1.accepts(set0));
445                 assert(repositoryGroup1.accepts(set1));
446             });
447         });
448     });
449
450     it('should create a test group with a custom root', () => {
451         return addTriggerableAndCreateTask('some task').then((taskId) => {
452             let insertedGroupId;
453             const webkit = Repository.all().filter((repository) => repository.name() == 'WebKit')[0];
454             const macos = Repository.all().filter((repository) => repository.name() == 'macOS')[0];
455             let uploadedFile;
456             return TemporaryFile.makeTemporaryFile('some.dat', 'some content').then((stream) => {
457                 return PrivilegedAPI.sendRequest('upload-file', {newFile: stream}, {useFormData: true});
458             }).then((response) => {
459                 uploadedFile = response['uploadedFile'];
460                 const revisionSets = [{[webkit.id()]: '191622', [macos.id()]: '15A284'},
461                     {[webkit.id()]: '191622', [macos.id()]: '15A284', 'customRoots': [uploadedFile['id']]}];
462                 return PrivilegedAPI.sendRequest('create-test-group', {name: 'test', task: taskId, repetitionCount: 2, revisionSets}).then((content) => {
463                     insertedGroupId = content['testGroupId'];
464                     return TestGroup.fetchByTask(taskId);
465                 });
466             }).then((testGroups) => {
467                 assert.equal(testGroups.length, 1);
468                 const group = testGroups[0];
469                 assert.equal(group.id(), insertedGroupId);
470                 assert.equal(group.repetitionCount(), 2);
471                 const requests = group.buildRequests();
472                 assert.equal(requests.length, 4);
473
474                 const set0 = requests[0].commitSet();
475                 const set1 = requests[1].commitSet();
476                 assert.equal(requests[2].commitSet(), set0);
477                 assert.equal(requests[3].commitSet(), set1);
478                 assert.deepEqual(Repository.sortByNamePreferringOnesWithURL(set0.repositories()), [webkit, macos]);
479                 assert.deepEqual(set0.customRoots(), []);
480                 assert.deepEqual(Repository.sortByNamePreferringOnesWithURL(set1.repositories()), [webkit, macos]);
481                 assert.deepEqual(set1.customRoots(), [UploadedFile.ensureSingleton(uploadedFile['id'], uploadedFile)]);
482                 assert.equal(set0.revisionForRepository(webkit), '191622');
483                 assert.equal(set0.revisionForRepository(webkit), set1.revisionForRepository(webkit));
484                 assert.equal(set0.commitForRepository(webkit), set1.commitForRepository(webkit));
485                 assert.equal(set0.revisionForRepository(macos), '15A284');
486                 assert.equal(set0.commitForRepository(macos), set1.commitForRepository(macos));
487                 assert.equal(set0.revisionForRepository(macos), set1.revisionForRepository(macos));
488                 assert(!set0.equals(set1));
489             });
490         });
491     });
492
493     it('should create a test group with an analysis task', () => {
494         let insertedGroupId;
495         let webkit;
496         return addTriggerableAndCreateTask('some task').then(() => {
497             webkit = Repository.all().filter((repository) => repository.name() == 'WebKit')[0];
498             const revisionSets = [{[webkit.id()]: '191622'}, {[webkit.id()]: '191623'}];
499             return PrivilegedAPI.sendRequest('create-test-group',
500                 {name: 'test', taskName: 'other task', platform: MockData.somePlatformId(), test: MockData.someTestId(), revisionSets});
501         }).then((result) => {
502             insertedGroupId = result['testGroupId'];
503             return Promise.all([AnalysisTask.fetchById(result['taskId']), TestGroup.fetchByTask(result['taskId'])]);
504         }).then((result) => {
505             const [analysisTask, testGroups] = result;
506
507             assert.equal(analysisTask.name(), 'other task');
508
509             assert.equal(testGroups.length, 1);
510             const group = testGroups[0];
511             assert.equal(group.id(), insertedGroupId);
512             assert.equal(group.repetitionCount(), 1);
513             const requests = group.buildRequests();
514             assert.equal(requests.length, 2);
515
516             const set0 = requests[0].commitSet();
517             const set1 = requests[1].commitSet();
518             assert.deepEqual(set0.repositories(), [webkit]);
519             assert.deepEqual(set0.customRoots(), []);
520             assert.deepEqual(set1.repositories(), [webkit]);
521             assert.deepEqual(set1.customRoots(), []);
522             assert.equal(set0.revisionForRepository(webkit), '191622');
523             assert.equal(set1.revisionForRepository(webkit), '191623');
524         });
525     });
526
527 });