Changeset 269871 in webkit
- Timestamp:
- Nov 16, 2020 12:32:08 PM (3 years ago)
- Location:
- trunk/Websites/perf.webkit.org
- Files:
-
- 12 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Websites/perf.webkit.org/ChangeLog
r269083 r269871 1 2020-10-30 Dewei Zhu <dewei_zhu@apple.com> 2 3 Performance dashboard should avoid building same configuration under one analysis task. 4 https://bugs.webkit.org/show_bug.cgi?id=218413 5 6 Reviewed by Ryosuke Niwa. 7 8 Add logic in syncing script to reuse already built roots from same build request under current analysis task. 9 If there is another same build request scheduled/running, will defer scheduling current build request. 10 11 * public/admin/platforms.php: Fixed newer version of PHP warns on accessing invalid key in an array. 12 * public/admin/tests.php: Added a null check against $selected_parent. 13 * public/api/build-requests.php: Extended this API to allow reusing roots from existing build request. 14 * public/v3/models/build-request.js: 15 (BuildRequest.prototype.async findBuildRequestWithSameRoots): Find build type build request with same commit set 16 which can/will be reused under current analysis task. 17 * public/v3/models/commit-set.js: 18 (CommitSet.prototype.equalsIgnoringRoot): Added a helper function which checks commit set equality ignoring the root. 19 (CommitSet.prototype.equals): Use '_equalsOptionallyIgnoringRoot' as underlying implementation. 20 (CommitSet.prototype._equalsOptionallyIgnoringRoot): Implementation for both equals and equalsIngnoringRoot. 21 * server-tests/api-build-requests-tests.js: Added unit tests. 22 * server-tests/resources/mock-data.js: Added new mock data for new unit tests. 23 (MockData.addMockConfiguration): 24 (MockData.addMockData): 25 (MockData.set addMockBuildRequestsWithRoots): 26 (MockData.set addTwoMockTestGroupWithOwnedCommits): 27 (MockData.mockTestSyncConfigWithPatchAcceptingBuilder): 28 * server-tests/tools-buildbot-triggerable-tests.js: Added unit tests. 29 * tools/js/buildbot-triggerable.js: 30 (BuildbotTriggerable.prototype.async syncOnce): 31 (BuildbotTriggerable.prototype.async _scheduleRequest): A helper function to reuse the roots if there are built 32 roots available for same build type build request. If there is another build scheduled for same build request, 33 will defer scheduling the build request. 34 * unit-tests/build-request-tests.js: Add unit tests. 35 1 36 2020-10-27 Dewei Zhu <dewei_zhu@apple.com> 2 37 -
trunk/Websites/perf.webkit.org/public/admin/platforms.php
r269083 r269871 103 103 global $platform_group_options; 104 104 $id = intval($platform_row['platform_id']); 105 $platform_group_id = $platform_row['platform_group'];105 $platform_group_id = array_get($platform_row, 'platform_group'); 106 106 $content = <<< END 107 107 <form method="POST"><input type="hidden" name="id" value="$id"> -
trunk/Websites/perf.webkit.org/public/admin/tests.php
r202000 r269871 65 65 66 66 foreach ($test_name_resolver->tests() as $test) { 67 if ($ test['test_parent'] != $selected_parent['test_id'])67 if ($selected_parent && $test['test_parent'] != $selected_parent['test_id']) 68 68 continue; 69 69 -
trunk/Websites/perf.webkit.org/public/api/build-requests.php
r250465 r269871 48 48 $url = array_get($info, 'url'); 49 49 $status_description = array_get($info, 'statusDescription'); 50 $build_request_for_root_reuse_id = array_get($info, 'buildRequestForRootReuse'); 50 51 $request_row = $db->select_first_row('build_requests', 'request', array('id' => $id)); 51 52 if ($status == 'failedIfNotCompleted') { … … 69 70 } 70 71 $db->update_row('build_requests', 'request', array('id' => $id), array('status' => $status, 'url' => $url, 'status_description' => $status_description)); 72 if ($build_request_for_root_reuse_id) { 73 $build_request_for_root_reuse_id = intval($build_request_for_root_reuse_id); 74 $build_request_for_root_reuse = $db->select_first_row('build_requests', 'request', array('id' => $build_request_for_root_reuse_id)); 75 if (!$build_request_for_root_reuse) { 76 $db->rollback_transaction(); 77 exit_with_error('FailedToFindbuildRequestForRootReuse', array('buildRequest' => $build_request_for_root_reuse_id)); 78 } 79 if ($build_request_for_root_reuse['request_status'] != 'completed') { 80 $db->rollback_transaction(); 81 exit_with_error('CanOnlyReuseCompletedBuildRequest', array('buildRequest' => $build_request_for_root_reuse_id, 'status' => $build_request_for_root_reuse['request_status'])); 82 } 83 $error = reuse_roots_in_commit_set($db, $build_request_for_root_reuse['request_commit_set'], $request_row['request_commit_set']); 84 if ($error) { 85 $db->rollback_transaction(); 86 exit_with_error($error['status'], $error['details']); 87 } 88 } 71 89 if ($status != 'failed') 72 90 continue; … … 83 101 } 84 102 103 function reuse_roots_in_commit_set($db, $source_id, $destination_id) { 104 $commit_set_items_source = $db->query_and_fetch_all('SELECT * FROM commit_set_items WHERE commitset_set = $1 AND commitset_commit IS NOT NULL', array($source_id)); 105 $commit_set_items_destination = $db->query_and_fetch_all('SELECT * FROM commit_set_items WHERE commitset_set = $1 AND commitset_commit IS NOT NULL', array($destination_id)); 106 if (count($commit_set_items_source) != count($commit_set_items_destination)) { 107 return array('status' => 'CannotReuseRootWithNonMatchingCommitSets', 'details' => array('sourceCommitSet' => $source_id, 108 'destinationCommitSet' => $destination_id)); 109 } 110 111 $root_file_ids = array(); 112 foreach ($commit_set_items_destination as &$destination_item) { 113 $source_item = NULL; 114 foreach ($commit_set_items_source as &$item) { 115 if ($destination_item['commitset_commit'] == $item['commitset_commit'] 116 && $destination_item['commitset_patch_file'] == $item['commitset_patch_file'] 117 && $destination_item['commitset_commit_owner'] == $item['commitset_commit_owner'] 118 && $destination_item['commitset_requires_build'] == $item['commitset_requires_build']) { 119 $source_item = $item; 120 break; 121 } 122 } 123 if (!$source_item) 124 return array('status' => 'NoMatchingCommitSetItem', 'details' => array('commitSet' => $source_id)); 125 126 $root_file_id = $source_item['commitset_root_file']; 127 if (!$root_file_id) { 128 if (!$db->is_true($source_item['commitset_requires_build'])) 129 continue; 130 return array('status' => 'MissingRootFileFromSourceCommitSet', 'details' => array('commitSet' => $destination_id, 'rootFile' => $root_file_id)); 131 } 132 133 $root_file_row = $db->select_first_row('uploaded_files', 'file', array('id' => $root_file_id)); 134 if ($root_file_row['file_deleted_at']) 135 return array('status' => 'CannotReuseDeletedRoot', 'details' => array('commitSet' => $destination_id, 'rootFile' => $root_file_id)); 136 137 $db->update_row('commit_set_items', 'commitset', array('set' => $destination_id, 'commit' => $destination_item['commitset_commit']), 138 array('root_file' => $root_file_id), 'set'); 139 140 array_push($root_file_ids, $root_file_id); 141 } 142 143 // There could be a race that those root files get purged after updating commit_set_items. 144 // Add another round of check to ensure they are not deleted by the end of this function to 145 // mitigate the race condition. 146 foreach ($root_file_ids as &$root_file_id) { 147 $root_file_row = $db->select_first_row('uploaded_files', 'file', array('id' => $root_file_id)); 148 if ($root_file_row['file_deleted_at']) 149 return array('status' => 'CannotReuseDeletedRoot', 'details' => array('commitSet' => $destination_id, 'rootFile' => $root_file_id)); 150 } 151 152 return NULL; 153 } 154 85 155 main(array_get($_GET, 'id'), 86 156 array_key_exists('PATH_INFO', $_SERVER) ? explode('/', trim($_SERVER['PATH_INFO'], '/')) : array(), -
trunk/Websites/perf.webkit.org/public/v3/models/build-request.js
r250465 r269871 88 88 buildId() { return this._buildId; } 89 89 createdAt() { return this._createdAt; } 90 91 static formatTimeInterval(intervalInMillionSeconds) { 90 async findBuildRequestWithSameRoots() 91 { 92 if (!this.isBuild()) 93 return null; 94 let scheduledBuildRequest = null; 95 let runningBuildRequest = null; 96 // Set ignoreCache = true as latest status of test groups is expected. 97 const allTestGroupsInTask = await TestGroup.fetchForTask(this.analysisTaskId(), true); 98 for (const group of allTestGroupsInTask) { 99 if (group.id() == this.testGroupId()) 100 continue; 101 if (group.isHidden()) 102 continue; 103 for (const buildRequest of group.buildRequests()) { 104 if (!buildRequest.isBuild()) 105 continue; 106 if (!this.platform().isInSameGroupAs(buildRequest.platform())) 107 continue; 108 if (!buildRequest.commitSet().equalsIgnoringRoot(this.commitSet())) 109 continue; 110 if (!buildRequest.commitSet().areAllRootsAvailable()) 111 continue; 112 if (buildRequest.hasCompleted()) 113 return buildRequest; 114 if (buildRequest.isScheduled() 115 && (!scheduledBuildRequest || buildRequest.createdAt() < scheduledBuildRequest.createdAt())) { 116 scheduledBuildRequest = buildRequest; 117 } 118 if (buildRequest.status() == 'running' 119 && (!runningBuildRequest || buildRequest.createdAt() < runningBuildRequest.createdAt())) { 120 runningBuildRequest = buildRequest; 121 } 122 } 123 } 124 return runningBuildRequest || scheduledBuildRequest; 125 } 126 127 static formatTimeInterval(intervalInMillionSeconds) 128 { 92 129 let intervalInSeconds = intervalInMillionSeconds / 1000; 93 130 const units = [ -
trunk/Websites/perf.webkit.org/public/v3/models/commit-set.js
r246581 r269871 75 75 commits() { return Array.from(this._repositoryToCommitMap.values()); } 76 76 77 areAllRootsAvailable() 78 { 79 return this.allRootFiles().every(rootFile => !rootFile.deletedAt() || this.customRoots().find(rootFile)); 80 } 81 77 82 revisionForRepository(repository) 78 83 { … … 103 108 } 104 109 110 equalsIgnoringRoot(other) 111 { 112 return this._equalsOptionallyIgnoringRoot(other, true); 113 } 114 105 115 equals(other) 116 { 117 return this._equalsOptionallyIgnoringRoot(other, false); 118 } 119 120 _equalsOptionallyIgnoringRoot(other, ignoringRoot) 106 121 { 107 122 if (this._repositories.length != other._repositories.length) … … 112 127 if (this.patchForRepository(repository) != other.patchForRepository(repository)) 113 128 return false; 114 if (this.rootForRepository(repository) != other.rootForRepository(repository) )129 if (this.rootForRepository(repository) != other.rootForRepository(repository) && !ignoringRoot) 115 130 return false; 116 131 if (this.ownerCommitForRepository(repository) != other.ownerCommitForRepository(repository)) -
trunk/Websites/perf.webkit.org/public/v3/models/platform.js
r269083 r269871 23 23 var map = this.namedStaticMap('name'); 24 24 return map ? map[name] : null; 25 } 26 27 isInSameGroupAs(other) 28 { 29 if (!this.group() && !other.group()) 30 return this == other; 31 return this.group() == other.group(); 25 32 } 26 33 -
trunk/Websites/perf.webkit.org/server-tests/api-build-requests-tests.js
r250465 r269871 6 6 let TestServer = require('./resources/test-server.js'); 7 7 const prepareServerTest = require('./resources/common-operations.js').prepareServerTest; 8 const assertThrows = require('../server-tests/resources/common-operations').assertThrows; 9 const crypto = require('crypto'); 8 10 9 11 describe('/api/build-requests', function () { … … 63 65 assert.deepEqual(content['buildRequests'][3], {id: '707', task: '1080', triggerable: '1000', repositoryGroup: '2001', test: '200', platform: '65', testGroup: '900', order: '3', commitSet: '404', status: 'pending', statusDescription: null, url: null, build: null, createdAt: 0}); 64 66 }); 67 }); 68 69 it('reuse roots from existing build requests if the commits sets are equal except the existence of roots', async () => { 70 await MockData.addMockBuildRequestsWithRoots(TestServer.database()); 71 let content = await TestServer.remoteAPI().getJSONWithStatus('/api/build-requests/build-webkit'); 72 73 assert.deepEqual(Object.keys(content).sort(), ['buildRequests', 'commitSets', 'commits', 'status', 'uploadedFiles']); 74 assert.equal(content['commitSets'].length, 4); 75 assert.equal(content['commitSets'][0].id, 500); 76 assert.equal(content['commitSets'][2].id, 600); 77 78 assert.deepEqual(content['commitSets'][0].revisionItems, [ 79 {commit: '87832', commitOwner: null, patch: null, requiresBuild: false, rootFile: null}, 80 {commit: '93116', commitOwner: null, patch: 100, requiresBuild: true, rootFile: 101}]); 81 assert.deepEqual(content['commitSets'][2].revisionItems, [ 82 {commit: '87832', commitOwner: null, patch: null, requiresBuild: false, rootFile: null}, 83 {commit: '93116', commitOwner: null, patch: 100, requiresBuild: true, rootFile: null}]); 84 85 assert.equal(content['buildRequests'].length, 8); 86 assert.equal(content['buildRequests'][0].id, 800); 87 assert.equal(content['buildRequests'][0].commitSet, 500); 88 assert.equal(content['buildRequests'][0].status, 'completed'); 89 assert.equal(content['buildRequests'][0].url, 'http://build.webkit.org/buids/1'); 90 assert.equal(content['buildRequests'][4].id, 900); 91 assert.equal(content['buildRequests'][4].commitSet, 600); 92 assert.equal(content['buildRequests'][4].status, 'pending'); 93 assert.equal(content['buildRequests'][4].url, null); 94 95 const updates = {900: { 96 status: content['buildRequests'][0].status, url: content['buildRequests'][0].url, buildRequestForRootReuse: content['buildRequests'][0].id}}; 97 const response = await TestServer.remoteAPI().postJSONWithStatus('/api/build-requests/build-webkit', { 98 'slaveName': 'sync-slave', 99 'slavePassword': 'password', 100 'buildRequestUpdates': updates 101 }); 102 103 content = await TestServer.remoteAPI().getJSONWithStatus('/api/build-requests/build-webkit'); 104 assert.equal(content['commitSets'].length, 4); 105 assert.equal(content['commitSets'][0].id, 500); 106 assert.equal(content['commitSets'][2].id, 600); 107 assert.deepEqual(content['commitSets'][0].revisionItems, [ 108 {commit: '87832', commitOwner: null, patch: null, requiresBuild: false, rootFile: null}, 109 {commit: '93116', commitOwner: null, patch: 100, requiresBuild: true, rootFile: 101}]); 110 assert.deepEqual(content['commitSets'][2].revisionItems, [ 111 {commit: '87832', commitOwner: null, patch: null, requiresBuild: false, rootFile: null}, 112 {commit: '93116', commitOwner: null, patch: 100, requiresBuild: true, rootFile: 101}]); 113 114 assert.equal(content['buildRequests'].length, 8); 115 assert.equal(content['buildRequests'][0].id, 800); 116 assert.equal(content['buildRequests'][0].commitSet, 500); 117 assert.equal(content['buildRequests'][0].status, 'completed'); 118 assert.equal(content['buildRequests'][0].url, 'http://build.webkit.org/buids/1'); 119 assert.equal(content['buildRequests'][4].id, 900); 120 assert.equal(content['buildRequests'][4].commitSet, 600); 121 assert.equal(content['buildRequests'][4].status, 'completed'); 122 assert.equal(content['buildRequests'][4].url, 'http://build.webkit.org/buids/1'); 123 }); 124 125 it('should reuse root built for owned commit if same completed build request exists', async () => { 126 await MockData.addTwoMockTestGroupWithOwnedCommits(TestServer.database()); 127 let content = await TestServer.remoteAPI().getJSONWithStatus('/api/build-requests/build-webkit'); 128 assert.deepEqual(Object.keys(content).sort(), ['buildRequests', 'commitSets', 'commits', 'status', 'uploadedFiles']); 129 assert.equal(content['commitSets'].length, 4); 130 assert.equal(content['commitSets'][0].id, 403); 131 assert.equal(content['commitSets'][2].id, 405); 132 133 assert.deepEqual(content['commitSets'][0].revisionItems, [ 134 {commit: '87832', commitOwner: null, patch: null, requiresBuild: false, rootFile: null}, 135 {commit: '93116', commitOwner: null, patch: null, requiresBuild: false, rootFile: null}, 136 {commit: '1797', commitOwner: '93116', patch: null, requiresBuild: true, rootFile: 101}]); 137 assert.deepEqual(content['commitSets'][2].revisionItems, [ 138 {commit: '87832', commitOwner: null, patch: null, requiresBuild: false, rootFile: null}, 139 {commit: '93116', commitOwner: null, patch: null, requiresBuild: false, rootFile: null}, 140 {commit: '1797', commitOwner: '93116', patch: null, requiresBuild: true, rootFile: null}]); 141 142 assert.equal(content['buildRequests'].length, 8); 143 assert.equal(content['buildRequests'][0].id, 704); 144 assert.equal(content['buildRequests'][0].commitSet, 403); 145 assert.equal(content['buildRequests'][0].status, 'completed'); 146 assert.equal(content['buildRequests'][0].url, 'http://build.webkit.org/buids/1'); 147 assert.equal(content['buildRequests'][4].id, 708); 148 assert.equal(content['buildRequests'][4].commitSet, 405); 149 assert.equal(content['buildRequests'][4].status, 'pending'); 150 assert.equal(content['buildRequests'][4].url, null); 151 152 const updates = {708: { 153 status: content['buildRequests'][0].status, url: content['buildRequests'][0].url, buildRequestForRootReuse: 704}}; 154 155 const response = await TestServer.remoteAPI().postJSONWithStatus('/api/build-requests/build-webkit', { 156 'slaveName': 'sync-slave', 157 'slavePassword': 'password', 158 'buildRequestUpdates': updates 159 }); 160 161 content = await TestServer.remoteAPI().getJSONWithStatus('/api/build-requests/build-webkit'); 162 assert.deepEqual(Object.keys(content).sort(), ['buildRequests', 'commitSets', 'commits', 'status', 'uploadedFiles']); 163 assert.equal(content['commitSets'].length, 4); 164 assert.equal(content['commitSets'][0].id, 403); 165 assert.equal(content['commitSets'][2].id, 405); 166 167 assert.deepEqual(content['commitSets'][0].revisionItems, [ 168 {commit: '87832', commitOwner: null, patch: null, requiresBuild: false, rootFile: null}, 169 {commit: '93116', commitOwner: null, patch: null, requiresBuild: false, rootFile: null}, 170 {commit: '1797', commitOwner: '93116', patch: null, requiresBuild: true, rootFile: 101}]); 171 assert.deepEqual(content['commitSets'][2].revisionItems, [ 172 {commit: '87832', commitOwner: null, patch: null, requiresBuild: false, rootFile: null}, 173 {commit: '93116', commitOwner: null, patch: null, requiresBuild: false, rootFile: null}, 174 {commit: '1797', commitOwner: '93116', patch: null, requiresBuild: true, rootFile: 101}]); 175 176 assert.equal(content['buildRequests'].length, 8); 177 assert.equal(content['buildRequests'][0].id, 704); 178 assert.equal(content['buildRequests'][0].commitSet, 403); 179 assert.equal(content['buildRequests'][0].status, 'completed'); 180 assert.equal(content['buildRequests'][0].url, 'http://build.webkit.org/buids/1'); 181 assert.equal(content['buildRequests'][4].id, 708); 182 assert.equal(content['buildRequests'][4].commitSet, 405); 183 assert.equal(content['buildRequests'][4].status, 'completed'); 184 assert.equal(content['buildRequests'][0].url, 'http://build.webkit.org/buids/1'); 185 }); 186 187 it('reuse roots from existing build requests if the commits sets are equal except the existence of custom roots', async () => { 188 const db = TestServer.database(); 189 await MockData.addMockBuildRequestsWithRoots(db); 190 await Promise.all([ 191 db.insert('uploaded_files', {id: 103, filename: 'custom-root-103', extension: '.tgz', size: 1, sha256: crypto.createHash('sha256').update('custom-root-103').digest('hex')}), 192 db.insert('commit_set_items', {set: 500, commit: null, patch_file: null, requires_build: false, root_file: 103}), 193 db.insert('uploaded_files', {id: 104, filename: 'custom-root-104', extension: '.tgz', size: 1, sha256: crypto.createHash('sha256').update('custom-root-104').digest('hex')}), 194 db.insert('commit_set_items', {set: 600, commit: null, patch_file: null, requires_build: false, root_file: 104}), 195 ]); 196 let content = await TestServer.remoteAPI().getJSONWithStatus('/api/build-requests/build-webkit'); 197 198 assert.deepEqual(Object.keys(content).sort(), ['buildRequests', 'commitSets', 'commits', 'status', 'uploadedFiles']); 199 assert.equal(content['commitSets'].length, 4); 200 assert.equal(content['commitSets'][0].id, 500); 201 assert.equal(content['commitSets'][2].id, 600); 202 203 assert.deepEqual(content['commitSets'][0].revisionItems, [ 204 {commit: '87832', commitOwner: null, patch: null, requiresBuild: false, rootFile: null}, 205 {commit: '93116', commitOwner: null, patch: 100, requiresBuild: true, rootFile: 101}]); 206 assert.deepEqual(content['commitSets'][2].revisionItems, [ 207 {commit: '87832', commitOwner: null, patch: null, requiresBuild: false, rootFile: null}, 208 {commit: '93116', commitOwner: null, patch: 100, requiresBuild: true, rootFile: null}]); 209 assert.deepEqual(content['commitSets'][0].customRoots, [103]); 210 assert.deepEqual(content['commitSets'][2].customRoots, [104]); 211 212 assert.equal(content['buildRequests'].length, 8); 213 assert.equal(content['buildRequests'][0].id, 800); 214 assert.equal(content['buildRequests'][0].commitSet, 500); 215 assert.equal(content['buildRequests'][0].status, 'completed'); 216 assert.equal(content['buildRequests'][0].url, 'http://build.webkit.org/buids/1'); 217 assert.equal(content['buildRequests'][4].id, 900); 218 assert.equal(content['buildRequests'][4].commitSet, 600); 219 assert.equal(content['buildRequests'][4].status, 'pending'); 220 assert.equal(content['buildRequests'][4].url, null); 221 222 const updates = {900: { 223 status: content['buildRequests'][0].status, url: content['buildRequests'][0].url, buildRequestForRootReuse: content['buildRequests'][0].id}}; 224 const response = await TestServer.remoteAPI().postJSONWithStatus('/api/build-requests/build-webkit', { 225 'slaveName': 'sync-slave', 226 'slavePassword': 'password', 227 'buildRequestUpdates': updates 228 }); 229 230 content = await TestServer.remoteAPI().getJSONWithStatus('/api/build-requests/build-webkit'); 231 assert.equal(content['commitSets'].length, 4); 232 assert.equal(content['commitSets'][0].id, 500); 233 assert.equal(content['commitSets'][2].id, 600); 234 assert.deepEqual(content['commitSets'][0].revisionItems, [ 235 {commit: '87832', commitOwner: null, patch: null, requiresBuild: false, rootFile: null}, 236 {commit: '93116', commitOwner: null, patch: 100, requiresBuild: true, rootFile: 101}]); 237 assert.deepEqual(content['commitSets'][2].revisionItems, [ 238 {commit: '87832', commitOwner: null, patch: null, requiresBuild: false, rootFile: null}, 239 {commit: '93116', commitOwner: null, patch: 100, requiresBuild: true, rootFile: 101}]); 240 assert.deepEqual(content['commitSets'][0].customRoots, [103]); 241 assert.deepEqual(content['commitSets'][2].customRoots, [104]); 242 243 assert.equal(content['buildRequests'].length, 8); 244 assert.equal(content['buildRequests'][0].id, 800); 245 assert.equal(content['buildRequests'][0].commitSet, 500); 246 assert.equal(content['buildRequests'][0].status, 'completed'); 247 assert.equal(content['buildRequests'][0].url, 'http://build.webkit.org/buids/1'); 248 assert.equal(content['buildRequests'][4].id, 900); 249 assert.equal(content['buildRequests'][4].commitSet, 600); 250 assert.equal(content['buildRequests'][4].status, 'completed'); 251 assert.equal(content['buildRequests'][4].url, 'http://build.webkit.org/buids/1'); 252 }); 253 254 it('should fail request with "CannotReuseDeletedRoot" if any root to reuse is deleted', async () => { 255 await MockData.addMockBuildRequestsWithRoots(TestServer.database()); 256 await TestServer.database().query("UPDATE uploaded_files SET file_deleted_at = now() at time zone 'utc' WHERE file_id=101"); 257 const content = await TestServer.remoteAPI().getJSONWithStatus('/api/build-requests/build-webkit'); 258 259 assert.deepEqual(Object.keys(content).sort(), ['buildRequests', 'commitSets', 'commits', 'status', 'uploadedFiles']); 260 assert.equal(content['commitSets'].length, 4); 261 assert.equal(content['commitSets'][0].id, 500); 262 assert.equal(content['commitSets'][2].id, 600); 263 264 assert.deepEqual(content['commitSets'][0].revisionItems, [ 265 {commit: '87832', commitOwner: null, patch: null, requiresBuild: false, rootFile: null}, 266 {commit: '93116', commitOwner: null, patch: 100, requiresBuild: true, rootFile: 101}]); 267 assert.deepEqual(content['commitSets'][2].revisionItems, [ 268 {commit: '87832', commitOwner: null, patch: null, requiresBuild: false, rootFile: null}, 269 {commit: '93116', commitOwner: null, patch: 100, requiresBuild: true, rootFile: null}]); 270 271 assert.equal(content['buildRequests'].length, 8); 272 assert.equal(content['buildRequests'][0].id, 800); 273 assert.equal(content['buildRequests'][0].commitSet, 500); 274 assert.equal(content['buildRequests'][0].status, 'completed'); 275 assert.equal(content['buildRequests'][0].url, 'http://build.webkit.org/buids/1'); 276 assert.equal(content['buildRequests'][4].id, 900); 277 assert.equal(content['buildRequests'][4].commitSet, 600); 278 assert.equal(content['buildRequests'][4].status, 'pending'); 279 assert.equal(content['buildRequests'][4].url, null); 280 281 const updates = {900: { 282 status: content['buildRequests'][0].status, url: content['buildRequests'][0].url, buildRequestForRootReuse: content['buildRequests'][0].id}}; 283 await assertThrows('CannotReuseDeletedRoot', () => TestServer.remoteAPI().postJSONWithStatus('/api/build-requests/build-webkit', { 284 'slaveName': 'sync-slave', 285 'slavePassword': 'password', 286 'buildRequestUpdates': updates 287 })); 288 }); 289 290 it('should fail request with "CannotReuseDeletedRoot" if any root to reuse is deleted while updating commit set items ', async () => { 291 await MockData.addMockBuildRequestsWithRoots(TestServer.database()); 292 await TestServer.database().query(`CREATE OR REPLACE FUNCTION emunlate_file_purge() RETURNS TRIGGER AS $emunlate_file_purge$ 293 BEGIN 294 UPDATE uploaded_files SET file_deleted_at = (CURRENT_TIMESTAMP AT TIME ZONE 'UTC') WHERE file_id = NEW.commitset_root_file; 295 RETURN NULL; 296 END; 297 $emunlate_file_purge$ LANGUAGE plpgsql;`); 298 await TestServer.database().query(`CREATE TRIGGER emunlate_file_purge AFTER UPDATE OF commitset_root_file ON commit_set_items 299 FOR EACH ROW EXECUTE PROCEDURE emunlate_file_purge();`); 300 const content = await TestServer.remoteAPI().getJSONWithStatus('/api/build-requests/build-webkit'); 301 302 assert.deepEqual(Object.keys(content).sort(), ['buildRequests', 'commitSets', 'commits', 'status', 'uploadedFiles']); 303 assert.equal(content['commitSets'].length, 4); 304 assert.equal(content['commitSets'][0].id, 500); 305 assert.equal(content['commitSets'][2].id, 600); 306 307 assert.deepEqual(content['commitSets'][0].revisionItems, [ 308 {commit: '87832', commitOwner: null, patch: null, requiresBuild: false, rootFile: null}, 309 {commit: '93116', commitOwner: null, patch: 100, requiresBuild: true, rootFile: 101}]); 310 assert.deepEqual(content['commitSets'][2].revisionItems, [ 311 {commit: '87832', commitOwner: null, patch: null, requiresBuild: false, rootFile: null}, 312 {commit: '93116', commitOwner: null, patch: 100, requiresBuild: true, rootFile: null}]); 313 314 assert.equal(content['buildRequests'].length, 8); 315 assert.equal(content['buildRequests'][0].id, 800); 316 assert.equal(content['buildRequests'][0].commitSet, 500); 317 assert.equal(content['buildRequests'][0].status, 'completed'); 318 assert.equal(content['buildRequests'][0].url, 'http://build.webkit.org/buids/1'); 319 assert.equal(content['buildRequests'][4].id, 900); 320 assert.equal(content['buildRequests'][4].commitSet, 600); 321 assert.equal(content['buildRequests'][4].status, 'pending'); 322 assert.equal(content['buildRequests'][4].url, null); 323 324 const updates = {900: { 325 status: content['buildRequests'][0].status, url: content['buildRequests'][0].url, buildRequestForRootReuse: content['buildRequests'][0].id}}; 326 327 await assertThrows('CannotReuseDeletedRoot', () => TestServer.remoteAPI().postJSONWithStatus('/api/build-requests/build-webkit', { 328 'slaveName': 'sync-slave', 329 'slavePassword': 'password', 330 'buildRequestUpdates': updates 331 })); 332 }); 333 334 it('should fail request with "NoMatchingCommitSetItem" if build request to reuse does not have patch', async () => { 335 await MockData.addMockData(TestServer.database(), ['completed', 'pending', 'pending', 'pending'], true, ['http://build.webkit.org/buids/2', null, null, null]); 336 await MockData.addMockBuildRequestsWithRoots(TestServer.database(), ['running', 'pending', 'pending', 'pending', 'pending', 'pending', 'pending', 'pending'], true, false); 337 const content = await TestServer.remoteAPI().getJSONWithStatus('/api/build-requests/build-webkit'); 338 339 assert.equal(content['commitSets'].length, 6); 340 assert.equal(content['commitSets'][0].id, 401); 341 assert.equal(content['commitSets'][4].id, 600); 342 343 assert.deepEqual(content['commitSets'][0].revisionItems, [ 344 {commit: '87832', commitOwner: null, patch: null, requiresBuild: false, rootFile: null}, 345 {commit: '93116', commitOwner: null, patch: null, requiresBuild: false, rootFile: null}]); 346 assert.deepEqual(content['commitSets'][4].revisionItems, [ 347 {commit: '87832', commitOwner: null, patch: null, requiresBuild: false, rootFile: null}, 348 {commit: '93116', commitOwner: null, patch: 100, requiresBuild: true, rootFile: null}]); 349 350 assert.equal(content['buildRequests'].length, 12); 351 assert.equal(content['buildRequests'][0].id, 700); 352 assert.equal(content['buildRequests'][0].commitSet, 401); 353 assert.equal(content['buildRequests'][0].status, 'completed'); 354 assert.equal(content['buildRequests'][0].url, 'http://build.webkit.org/buids/2'); 355 assert.equal(content['buildRequests'][8].id, 900); 356 assert.equal(content['buildRequests'][8].commitSet, 600); 357 assert.equal(content['buildRequests'][8].status, 'pending'); 358 assert.equal(content['buildRequests'][8].url, null); 359 360 const updates = {900: { 361 status: content['buildRequests'][0].status, url: content['buildRequests'][0].url, buildRequestForRootReuse: content['buildRequests'][0].id}}; 362 363 await assertThrows('NoMatchingCommitSetItem', () => TestServer.remoteAPI().postJSONWithStatus('/api/build-requests/build-webkit', { 364 'slaveName': 'sync-slave', 365 'slavePassword': 'password', 366 'buildRequestUpdates': updates 367 })); 368 }); 369 370 it('should fail request with "CannotReuseRootWithNonMatchingCommitSets" if commit sets have different number of entries', async () => { 371 await MockData.addMockData(TestServer.database(), ['completed', 'pending', 'pending', 'pending'], true, ['http://build.webkit.org/buids/2', null, null, null]); 372 await MockData.addMockBuildRequestsWithRoots(TestServer.database(), ['running', 'pending', 'pending', 'pending', 'pending', 'pending', 'pending', 'pending'], true, false); 373 await TestServer.database().insert('commit_set_items', {set: 401, commit: 111168}) 374 const content = await TestServer.remoteAPI().getJSONWithStatus('/api/build-requests/build-webkit'); 375 376 assert.equal(content['commitSets'].length, 6); 377 assert.equal(content['commitSets'][0].id, 401); 378 assert.equal(content['commitSets'][4].id, 600); 379 380 assert.deepEqual(content['commitSets'][0].revisionItems, [ 381 {commit: '87832', commitOwner: null, patch: null, requiresBuild: false, rootFile: null}, 382 {commit: '93116', commitOwner: null, patch: null, requiresBuild: false, rootFile: null}, 383 {commit: '111168', commitOwner: null, patch: null, requiresBuild: false, rootFile: null}]); 384 assert.deepEqual(content['commitSets'][4].revisionItems, [ 385 {commit: '87832', commitOwner: null, patch: null, requiresBuild: false, rootFile: null}, 386 {commit: '93116', commitOwner: null, patch: 100, requiresBuild: true, rootFile: null}]); 387 388 assert.equal(content['buildRequests'].length, 12); 389 assert.equal(content['buildRequests'][0].id, 700); 390 assert.equal(content['buildRequests'][0].commitSet, 401); 391 assert.equal(content['buildRequests'][0].status, 'completed'); 392 assert.equal(content['buildRequests'][0].url, 'http://build.webkit.org/buids/2'); 393 assert.equal(content['buildRequests'][8].id, 900); 394 assert.equal(content['buildRequests'][8].commitSet, 600); 395 assert.equal(content['buildRequests'][8].status, 'pending'); 396 assert.equal(content['buildRequests'][8].url, null); 397 398 const updates = {900: { 399 status: content['buildRequests'][0].status, url: content['buildRequests'][0].url, buildRequestForRootReuse: content['buildRequests'][0].id}}; 400 401 await assertThrows('CannotReuseRootWithNonMatchingCommitSets', () => TestServer.remoteAPI().postJSONWithStatus('/api/build-requests/build-webkit', { 402 'slaveName': 'sync-slave', 403 'slavePassword': 'password', 404 'buildRequestUpdates': updates 405 })); 406 }); 407 408 it('should fail request with "CanOnlyReuseCompletedBuildRequest" if build request to reuse is not completed', async () => { 409 await MockData.addMockBuildRequestsWithRoots(TestServer.database(), ['running', 'pending', 'pending', 'pending', 'pending', 'pending', 'pending', 'pending']); 410 const content = await TestServer.remoteAPI().getJSONWithStatus('/api/build-requests/build-webkit'); 411 412 assert.deepEqual(Object.keys(content).sort(), ['buildRequests', 'commitSets', 'commits', 'status', 'uploadedFiles']); 413 assert.equal(content['commitSets'].length, 4); 414 assert.equal(content['commitSets'][0].id, 500); 415 assert.equal(content['commitSets'][2].id, 600); 416 417 assert.deepEqual(content['commitSets'][0].revisionItems, [ 418 {commit: '87832', commitOwner: null, patch: null, requiresBuild: false, rootFile: null}, 419 {commit: '93116', commitOwner: null, patch: 100, requiresBuild: true, rootFile: 101}]); 420 assert.deepEqual(content['commitSets'][2].revisionItems, [ 421 {commit: '87832', commitOwner: null, patch: null, requiresBuild: false, rootFile: null}, 422 {commit: '93116', commitOwner: null, patch: 100, requiresBuild: true, rootFile: null}]); 423 424 assert.equal(content['buildRequests'].length, 8); 425 assert.equal(content['buildRequests'][0].id, 800); 426 assert.equal(content['buildRequests'][0].commitSet, 500); 427 assert.equal(content['buildRequests'][0].status, 'running'); 428 assert.equal(content['buildRequests'][0].url, 'http://build.webkit.org/buids/1'); 429 assert.equal(content['buildRequests'][4].id, 900); 430 assert.equal(content['buildRequests'][4].commitSet, 600); 431 assert.equal(content['buildRequests'][4].status, 'pending'); 432 assert.equal(content['buildRequests'][4].url, null); 433 434 const updates = {900: { 435 status: content['buildRequests'][0].status, url: content['buildRequests'][0].url, buildRequestForRootReuse: content['buildRequests'][0].id}}; 436 await assertThrows('CanOnlyReuseCompletedBuildRequest', () => TestServer.remoteAPI().postJSONWithStatus('/api/build-requests/build-webkit', { 437 'slaveName': 'sync-slave', 438 'slavePassword': 'password', 439 'buildRequestUpdates': updates 440 })); 441 }); 442 443 it('should fail request with "FailedToFindReuseBuildRequest" if the build request to reuse does not exist', async () => { 444 await MockData.addMockBuildRequestsWithRoots(TestServer.database()); 445 const content = await TestServer.remoteAPI().getJSONWithStatus('/api/build-requests/build-webkit'); 446 447 assert.deepEqual(Object.keys(content).sort(), ['buildRequests', 'commitSets', 'commits', 'status', 'uploadedFiles']); 448 assert.equal(content['commitSets'].length, 4); 449 assert.equal(content['commitSets'][0].id, 500); 450 assert.equal(content['commitSets'][2].id, 600); 451 452 assert.deepEqual(content['commitSets'][0].revisionItems, [ 453 {commit: '87832', commitOwner: null, patch: null, requiresBuild: false, rootFile: null}, 454 {commit: '93116', commitOwner: null, patch: 100, requiresBuild: true, rootFile: 101}]); 455 assert.deepEqual(content['commitSets'][2].revisionItems, [ 456 {commit: '87832', commitOwner: null, patch: null, requiresBuild: false, rootFile: null}, 457 {commit: '93116', commitOwner: null, patch: 100, requiresBuild: true, rootFile: null}]); 458 459 assert.equal(content['buildRequests'].length, 8); 460 assert.equal(content['buildRequests'][0].id, 800); 461 assert.equal(content['buildRequests'][0].commitSet, 500); 462 assert.equal(content['buildRequests'][0].status, 'completed'); 463 assert.equal(content['buildRequests'][0].url, 'http://build.webkit.org/buids/1'); 464 assert.equal(content['buildRequests'][4].id, 900); 465 assert.equal(content['buildRequests'][4].commitSet, 600); 466 assert.equal(content['buildRequests'][4].status, 'pending'); 467 assert.equal(content['buildRequests'][4].url, null); 468 469 const updates = {900: { 470 status: content['buildRequests'][0].status, url: content['buildRequests'][0].url, buildRequestForRootReuse: 999}}; 471 472 await assertThrows('FailedToFindbuildRequestForRootReuse', () => TestServer.remoteAPI().postJSONWithStatus('/api/build-requests/build-webkit', { 473 'slaveName': 'sync-slave', 474 'slavePassword': 'password', 475 'buildRequestUpdates': updates 476 })); 65 477 }); 66 478 -
trunk/Websites/perf.webkit.org/server-tests/resources/mock-data.js
r251564 r269871 41 41 db.insert('repositories', {id: this.ownedJSCRepositoryId(), owner: this.webkitRepositoryId(), name: 'JavaScriptCore'}), 42 42 db.insert('repositories', {id: this.jscRepositoryId(), name: 'JavaScriptCore'}), 43 db.insert('triggerable_repository_groups', {id: 2001, name: 'webkit-svn', triggerable: 1000 }),43 db.insert('triggerable_repository_groups', {id: 2001, name: 'webkit-svn', triggerable: 1000, accepts_roots: true}), 44 44 db.insert('triggerable_repositories', {repository: this.macosRepositoryId(), group: 2001}), 45 db.insert('triggerable_repositories', {repository: this.webkitRepositoryId(), group: 2001 }),45 db.insert('triggerable_repositories', {repository: this.webkitRepositoryId(), group: 2001, accepts_patch: true}), 46 46 db.insert('commits', {id: 87832, repository: this.macosRepositoryId(), revision: '10.11 15A284'}), 47 47 db.insert('commits', {id: 93116, repository: this.webkitRepositoryId(), revision: '191622', time: (new Date(1445945816878)).toISOString()}), … … 65 65 ]); 66 66 }, 67 addMockData: function (db, statusList, needsNotification=true )67 addMockData: function (db, statusList, needsNotification=true, urlList=[]) 68 68 { 69 69 if (!statusList) 70 70 statusList = ['pending', 'pending', 'pending', 'pending']; 71 if (!urlList) 72 urlList = [null, null, null, null]; 71 73 return Promise.all([ 72 74 this.addMockConfiguration(db), … … 81 83 end_run: 801, end_run_time: '2015-10-27T12:05:27.1Z'}), 82 84 db.insert('analysis_test_groups', {id: 600, task: 500, name: 'some test group', initial_repetition_count: 4, needs_notification: needsNotification}), 83 db.insert('build_requests', {id: 700, status: statusList[0], triggerable: 1000, repository_group: 2001, platform: 65, test: 200, group: 600, order: 0, commit_set: 401}), 84 db.insert('build_requests', {id: 701, status: statusList[1], triggerable: 1000, repository_group: 2001, platform: 65, test: 200, group: 600, order: 1, commit_set: 402}), 85 db.insert('build_requests', {id: 702, status: statusList[2], triggerable: 1000, repository_group: 2001, platform: 65, test: 200, group: 600, order: 2, commit_set: 401}), 86 db.insert('build_requests', {id: 703, status: statusList[3], triggerable: 1000, repository_group: 2001, platform: 65, test: 200, group: 600, order: 3, commit_set: 402}), 85 db.insert('build_requests', {id: 700, status: statusList[0], url: urlList[0], triggerable: 1000, repository_group: 2001, platform: 65, test: 200, group: 600, order: 0, commit_set: 401}), 86 db.insert('build_requests', {id: 701, status: statusList[1], url: urlList[1], triggerable: 1000, repository_group: 2001, platform: 65, test: 200, group: 600, order: 1, commit_set: 402}), 87 db.insert('build_requests', {id: 702, status: statusList[2], url: urlList[2], triggerable: 1000, repository_group: 2001, platform: 65, test: 200, group: 600, order: 2, commit_set: 401}), 88 db.insert('build_requests', {id: 703, status: statusList[3], url: urlList[3], triggerable: 1000, repository_group: 2001, platform: 65, test: 200, group: 600, order: 3, commit_set: 402}), 89 ]); 90 }, 91 addMockBuildRequestsWithRoots(db, statusList, needsNotification=true, addMockConfiguration=true) 92 { 93 const setupSteps = addMockConfiguration ? [this.addMockConfiguration(db)] : []; 94 if (!statusList) 95 statusList = ['completed', 'running', 'pending', 'pending', 'pending', 'pending', 'pending', 'pending']; 96 return Promise.all([ 97 ...setupSteps, 98 db.insert('uploaded_files', {id: 100, filename: 'patch-100', extension: '.txt', size: 1, sha256: crypto.createHash('sha256').update('patch-100').digest('hex')}), 99 db.insert('uploaded_files', {id: 101, filename: 'root-101', extension: '.tgz', size: 1, sha256: crypto.createHash('sha256').update('root-101').digest('hex')}), 100 db.insert('uploaded_files', {id: 102, filename: 'patch-102', extension: '.txt', size: 1, sha256: crypto.createHash('sha256').update('patch-102').digest('hex')}), 101 102 db.insert('commit_sets', {id: 500}), 103 db.insert('commit_set_items', {set: 500, commit: 87832}), 104 db.insert('commit_set_items', {set: 500, commit: 93116, patch_file: 100, requires_build: true, root_file: 101}), 105 db.insert('commit_sets', {id: 501}), 106 db.insert('commit_set_items', {set: 501, commit: 87832}), 107 db.insert('commit_set_items', {set: 501, commit: 96336, patch_file: 102, requires_build: true}), 108 109 db.insert('commit_sets', {id: 600}), 110 db.insert('commit_set_items', {set: 600, commit: 87832}), 111 db.insert('commit_set_items', {set: 600, commit: 93116, patch_file: 100, requires_build: true}), 112 db.insert('commit_sets', {id: 601}), 113 db.insert('commit_set_items', {set: 601, commit: 87832}), 114 db.insert('commit_set_items', {set: 601, commit: 96336, patch_file: 102, requires_build: true}), 115 116 db.insert('analysis_tasks', {id: 600, name: 'another task'}), 117 118 db.insert('analysis_test_groups', {id: 700, task: 600, name: 'test with root built', initial_repetition_count: 1, needs_notification: needsNotification}), 119 db.insert('build_requests', {id: 800, status: statusList[0], triggerable: 1000, repository_group: 2001, platform: 65, group: 700, order: -2, commit_set: 500, url: 'http://build.webkit.org/buids/1'}), 120 db.insert('build_requests', {id: 801, status: statusList[1], triggerable: 1000, repository_group: 2001, platform: 65, group: 700, order: -1, commit_set: 501}), 121 db.insert('build_requests', {id: 802, status: statusList[2], triggerable: 1000, repository_group: 2001, platform: 65, test: 200, group: 700, order: 0, commit_set: 500}), 122 db.insert('build_requests', {id: 803, status: statusList[3], triggerable: 1000, repository_group: 2001, platform: 65, test: 200, group: 700, order: 1, commit_set: 501}), 123 124 db.insert('analysis_test_groups', {id: 701, task: 600, name: 'test will reuse root', initial_repetition_count: 1, needs_notification: needsNotification}), 125 db.insert('build_requests', {id: 900, status: statusList[4], triggerable: 1000, repository_group: 2001, platform: 65, group: 701, order: -2, commit_set: 600}), 126 db.insert('build_requests', {id: 901, status: statusList[5], triggerable: 1000, repository_group: 2001, platform: 65, group: 701, order: -1, commit_set: 601}), 127 db.insert('build_requests', {id: 902, status: statusList[6], triggerable: 1000, repository_group: 2001, platform: 65, test: 200, group: 701, order: 0, commit_set: 600}), 128 db.insert('build_requests', {id: 903, status: statusList[7], triggerable: 1000, repository_group: 2001, platform: 65, test: 200, group: 701, order: 1, commit_set: 601}), 87 129 ]); 88 130 }, … … 173 215 ]); 174 216 }, 217 addTwoMockTestGroupWithOwnedCommits(db) 218 { 219 return Promise.all([ 220 this.addMockConfiguration(db), 221 this.addAnotherTriggerable(db), 222 db.insert('analysis_tasks', {id: 1080, platform: 65, metric: 300, name: 'some task with component test', 223 start_run: 801, start_run_time: '2015-10-27T12:05:27.1Z', 224 end_run: 801, end_run_time: '2015-10-27T12:05:27.1Z'}), 225 226 db.insert('uploaded_files', {id: 101, filename: 'root-101', size: 1, sha256: crypto.createHash('sha256').update('root-101').digest('hex'), }), 227 db.insert('analysis_test_groups', {id: 900, task: 1080, name: 'some test group with component test(root built)', initial_repetition_count: 1}), 228 db.insert('commit_sets', {id: 403}), 229 db.insert('commit_set_items', {set: 403, commit: 87832}), 230 db.insert('commit_set_items', {set: 403, commit: 93116}), 231 db.insert('commit_set_items', {set: 403, commit: 1797, commit_owner: 93116, requires_build: true, root_file: 101}), 232 db.insert('commit_sets', {id: 404}), 233 db.insert('commit_set_items', {set: 404, commit: 87832}), 234 db.insert('commit_set_items', {set: 404, commit: 96336}), 235 db.insert('commit_set_items', {set: 404, commit: 2017, commit_owner: 96336, requires_build: true}), 236 db.insert('build_requests', {id: 704, status: 'completed', triggerable: 1000, repository_group: 2001, platform: 65, group: 900, order: -2, commit_set: 403, url: 'http://build.webkit.org/buids/1'}), 237 db.insert('build_requests', {id: 705, status: 'pending', triggerable: 1000, repository_group: 2001, platform: 65, group: 900, order: -1, commit_set: 404}), 238 db.insert('build_requests', {id: 706, status: 'pending', triggerable: 1000, repository_group: 2001, platform: 65, test: 200, group: 900, order: 0, commit_set: 403}), 239 db.insert('build_requests', {id: 707, status: 'pending', triggerable: 1000, repository_group: 2001, platform: 65, test: 200, group: 900, order: 1, commit_set: 404}), 240 241 db.insert('analysis_test_groups', {id: 901, task: 1080, name: 'some test group with component test', initial_repetition_count: 1}), 242 db.insert('commit_sets', {id: 405}), 243 db.insert('commit_set_items', {set: 405, commit: 87832}), 244 db.insert('commit_set_items', {set: 405, commit: 93116}), 245 db.insert('commit_set_items', {set: 405, commit: 1797, commit_owner: 93116, requires_build: true}), 246 db.insert('commit_sets', {id: 406}), 247 db.insert('commit_set_items', {set: 406, commit: 87832}), 248 db.insert('commit_set_items', {set: 406, commit: 96336}), 249 db.insert('commit_set_items', {set: 406, commit: 2017, commit_owner: 96336, requires_build: true}), 250 db.insert('build_requests', {id: 708, status: 'pending', triggerable: 1000, repository_group: 2001, platform: 65, group: 901, order: -2, commit_set: 405}), 251 db.insert('build_requests', {id: 709, status: 'pending', triggerable: 1000, repository_group: 2001, platform: 65, group: 901, order: -1, commit_set: 406}), 252 db.insert('build_requests', {id: 710, status: 'pending', triggerable: 1000, repository_group: 2001, platform: 65, test: 200, group: 901, order: 0, commit_set: 405}), 253 db.insert('build_requests', {id: 711, status: 'pending', triggerable: 1000, repository_group: 2001, platform: 65, test: 200, group: 901, order: 1, commit_set: 406}), 254 ]); 255 }, 175 256 addTestGroupWithOwnerCommitNotInCommitSet(db) 176 257 { … … 216 297 'types': ['some-test'], 217 298 'builders': ['builder-1'], 299 } 300 ] 301 } 302 }, 303 mockTestSyncConfigWithPatchAcceptingBuilder: function () 304 { 305 return { 306 'triggerableName': 'build-webkit', 307 'lookbackCount': 2, 308 'buildRequestArgument': 'build-request-id', 309 'repositoryGroups': { 310 'webkit-svn': { 311 'repositories': {'WebKit': {'acceptsPatch': true}, 'macOS': {}}, 312 'acceptsRoots': true, 313 'testProperties': { 314 'os': {'revision': 'macOS'}, 315 'wk': {'revision': 'WebKit'}, 316 'roots': {"roots": {}}, 317 }, 318 'buildProperties': { 319 'os': {'revision': 'macOS'}, 320 'wk': {'revision': 'WebKit'}, 321 'wk-patch': {'patch': 'WebKit'}, 322 } 323 } 324 }, 325 'types': { 326 'some-test': {'test': ['some test']} 327 }, 328 'builders': { 329 'tester': {'builder': 'some tester', properties: {forcescheduler: 'force-some-tester'}}, 330 'builder-1': {'builder': 'some-builder-1', properties: {forcescheduler: 'force-some-builder-1'}}, 331 'builder-2': {'builder': 'some builder 2', properties: {forcescheduler: 'force-some-builder-2'}}, 332 }, 333 'testConfigurations': [ 334 { 335 'platforms': ['some platform'], 336 'types': ['some-test'], 337 'builders': ['tester'], 338 } 339 ], 340 'buildConfigurations': [ 341 { 342 'platforms': ['some platform'], 343 'builders': ['builder-1', 'builder-2'], 218 344 } 219 345 ] -
trunk/Websites/perf.webkit.org/server-tests/tools-buildbot-triggerable-tests.js
r230960 r269871 946 946 MockRemoteAPI.requests[2].resolve('OK'); 947 947 }); 948 }); 949 950 it('should reuse the roots from a completed build request with the same commit set', async () => { 951 await MockData.addMockBuildRequestsWithRoots(TestServer.database()); 952 await Manifest.fetch(); 953 const config = MockData.mockTestSyncConfigWithPatchAcceptingBuilder(); 954 const logger = new MockLogger; 955 const slaveInfo = {name: 'sync-slave', password: 'password'}; 956 const triggerable = new BuildbotTriggerable(config, TestServer.remoteAPI(), MockRemoteAPI, slaveInfo, logger); 957 const syncPromise = triggerable.initSyncers().then(() => triggerable.syncOnce()); 958 assertRequestAndResolve(MockRemoteAPI.requests[0], 'GET', MockData.buildbotBuildersURL(), MockData.mockBuildbotBuilders()); 959 MockRemoteAPI.reset(); 960 await MockRemoteAPI.waitForRequest(); 961 962 assert.equal(BuildRequest.all().length, 8); 963 let buildRequest = BuildRequest.findById(800); 964 let anotherBuildRequest = BuildRequest.findById(900); 965 assert.equal(buildRequest.status(), 'completed'); 966 assert.equal(anotherBuildRequest.status(), 'pending'); 967 assert.equal(buildRequest.statusUrl(), 'http://build.webkit.org/buids/1'); 968 assert.equal(anotherBuildRequest.statusUrl(), null); 969 let commitSet = buildRequest.commitSet(); 970 let anotherCommitSet = anotherBuildRequest.commitSet(); 971 assert.ok(commitSet.equalsIgnoringRoot(anotherCommitSet)); 972 assert.ok(!commitSet.equals(anotherCommitSet)); 973 974 assert.equal(MockRemoteAPI.requests.length, 3); 975 assert.equal(MockRemoteAPI.requests[0].method, 'GET'); 976 assert.equal(MockRemoteAPI.requests[0].url, MockData.pendingBuildsUrl('some tester')); 977 MockRemoteAPI.requests[0].resolve({}); 978 assert.equal(MockRemoteAPI.requests[1].method, 'GET'); 979 assert.equal(MockRemoteAPI.requests[1].url, MockData.pendingBuildsUrl('some-builder-1')); 980 MockRemoteAPI.requests[1].resolve({}); 981 assert.equal(MockRemoteAPI.requests[2].method, 'GET'); 982 assert.equal(MockRemoteAPI.requests[2].url, MockData.pendingBuildsUrl('some builder 2')); 983 MockRemoteAPI.requests[2].resolve({}); 984 MockRemoteAPI.reset(); 985 await MockRemoteAPI.waitForRequest(); 986 987 assert.equal(MockRemoteAPI.requests.length, 3); 988 assert.equal(MockRemoteAPI.requests[0].method, 'GET'); 989 assert.equal(MockRemoteAPI.requests[0].url, MockData.recentBuildsUrl('some tester', 2)); 990 MockRemoteAPI.requests[0].resolve({}); 991 assert.equal(MockRemoteAPI.requests[1].method, 'GET'); 992 assert.equal(MockRemoteAPI.requests[1].url, MockData.recentBuildsUrl('some-builder-1', 2)); 993 MockRemoteAPI.requests[1].resolve({'builds': [MockData.runningBuildData({buildRequestId: 801}), MockData.finishedBuildData({buildRequestId: 800})]}); 994 assert.equal(MockRemoteAPI.requests[2].method, 'GET'); 995 assert.equal(MockRemoteAPI.requests[2].url, MockData.recentBuildsUrl('some builder 2', 2)); 996 MockRemoteAPI.requests[2].resolve({}); 997 MockRemoteAPI.reset(); 998 await MockRemoteAPI.waitForRequest(); 999 1000 assert.equal(MockRemoteAPI.requests.length, 3); 1001 assert.equal(MockRemoteAPI.requests[0].method, 'GET'); 1002 assert.equal(MockRemoteAPI.requests[0].url, MockData.pendingBuildsUrl('some tester')); 1003 MockRemoteAPI.requests[0].resolve({}); 1004 assert.equal(MockRemoteAPI.requests[1].method, 'GET'); 1005 assert.equal(MockRemoteAPI.requests[1].url, MockData.pendingBuildsUrl('some-builder-1')); 1006 MockRemoteAPI.requests[1].resolve({}); 1007 assert.equal(MockRemoteAPI.requests[2].method, 'GET'); 1008 assert.equal(MockRemoteAPI.requests[2].url, MockData.pendingBuildsUrl('some builder 2')); 1009 MockRemoteAPI.requests[2].resolve({}); 1010 MockRemoteAPI.reset(); 1011 await MockRemoteAPI.waitForRequest(); 1012 1013 assert.equal(MockRemoteAPI.requests.length, 3); 1014 assert.equal(MockRemoteAPI.requests[0].method, 'GET'); 1015 assert.equal(MockRemoteAPI.requests[0].url, MockData.recentBuildsUrl('some tester', 2)); 1016 MockRemoteAPI.requests[0].resolve({}); 1017 assert.equal(MockRemoteAPI.requests[1].method, 'GET'); 1018 assert.equal(MockRemoteAPI.requests[1].url, MockData.recentBuildsUrl('some-builder-1', 2)); 1019 MockRemoteAPI.requests[1].resolve({'builds': [MockData.runningBuildData({buildRequestId: 801}), MockData.finishedBuildData({buildRequestId: 800})]}); 1020 assert.equal(MockRemoteAPI.requests[2].method, 'GET'); 1021 assert.equal(MockRemoteAPI.requests[2].url, MockData.recentBuildsUrl('some builder 2', 2)); 1022 MockRemoteAPI.requests[2].resolve({}); 1023 MockRemoteAPI.reset(); 1024 1025 await syncPromise; 1026 await BuildRequest.fetchForTriggerable(MockData.mockTestSyncConfigWithPatchAcceptingBuilder().triggerableName); 1027 assert.equal(BuildRequest.all().length, 8); 1028 buildRequest = BuildRequest.findById(800); 1029 anotherBuildRequest = BuildRequest.findById(900); 1030 assert.equal(buildRequest.status(), 'completed'); 1031 assert.equal(anotherBuildRequest.status(), 'completed'); 1032 assert.equal(buildRequest.statusUrl(), 'http://build.webkit.org/buids/1'); 1033 assert.equal(anotherBuildRequest.statusUrl(), 'http://build.webkit.org/buids/1'); 1034 }); 1035 1036 it('should defer scheduling a build request if there is a "running" build request with same commit set, but should schedule the build request if "running" build request with same commit set fails later on', async () => { 1037 await MockData.addMockBuildRequestsWithRoots(TestServer.database(), ['running', 'scheduled', 'pending', 'pending', 'pending', 'pending', 'pending', 'pending']); 1038 await Manifest.fetch(); 1039 const config = MockData.mockTestSyncConfigWithPatchAcceptingBuilder(); 1040 const logger = new MockLogger; 1041 const slaveInfo = {name: 'sync-slave', password: 'password'}; 1042 const triggerable = new BuildbotTriggerable(config, TestServer.remoteAPI(), MockRemoteAPI, slaveInfo, logger); 1043 const syncPromise = triggerable.initSyncers().then(() => triggerable.syncOnce()); 1044 assertRequestAndResolve(MockRemoteAPI.requests[0], 'GET', MockData.buildbotBuildersURL(), MockData.mockBuildbotBuilders()); 1045 MockRemoteAPI.reset(); 1046 await MockRemoteAPI.waitForRequest(); 1047 1048 assert.equal(BuildRequest.all().length, 8); 1049 let buildRequest = BuildRequest.findById(800); 1050 let anotherBuildRequest = BuildRequest.findById(900); 1051 assert.equal(buildRequest.status(), 'running'); 1052 assert.equal(anotherBuildRequest.status(), 'pending'); 1053 assert.equal(buildRequest.statusUrl(), 'http://build.webkit.org/buids/1'); 1054 assert.equal(anotherBuildRequest.statusUrl(), null); 1055 let commitSet = buildRequest.commitSet(); 1056 let anotherCommitSet = anotherBuildRequest.commitSet(); 1057 assert.ok(commitSet.equalsIgnoringRoot(anotherCommitSet)); 1058 assert.ok(!commitSet.equals(anotherCommitSet)); 1059 1060 assert.equal(MockRemoteAPI.requests.length, 3); 1061 assert.equal(MockRemoteAPI.requests[0].method, 'GET'); 1062 assert.equal(MockRemoteAPI.requests[0].url, MockData.pendingBuildsUrl('some tester')); 1063 MockRemoteAPI.requests[0].resolve({}); 1064 assert.equal(MockRemoteAPI.requests[1].method, 'GET'); 1065 assert.equal(MockRemoteAPI.requests[1].url, MockData.pendingBuildsUrl('some-builder-1')); 1066 MockRemoteAPI.requests[1].resolve({'builds': [MockData.pendingBuild({buildRequestId: 801})]}); 1067 assert.equal(MockRemoteAPI.requests[2].method, 'GET'); 1068 assert.equal(MockRemoteAPI.requests[2].url, MockData.pendingBuildsUrl('some builder 2')); 1069 MockRemoteAPI.requests[2].resolve({}); 1070 MockRemoteAPI.reset(); 1071 await MockRemoteAPI.waitForRequest(); 1072 1073 assert.equal(MockRemoteAPI.requests.length, 3); 1074 assert.equal(MockRemoteAPI.requests[0].method, 'GET'); 1075 assert.equal(MockRemoteAPI.requests[0].url, MockData.recentBuildsUrl('some tester', 2)); 1076 MockRemoteAPI.requests[0].resolve({}); 1077 assert.equal(MockRemoteAPI.requests[1].method, 'GET'); 1078 assert.equal(MockRemoteAPI.requests[1].url, MockData.recentBuildsUrl('some-builder-1', 2)); 1079 MockRemoteAPI.requests[1].resolve({'builds': [MockData.runningBuildData({buildRequestId: 800})]}); 1080 assert.equal(MockRemoteAPI.requests[2].method, 'GET'); 1081 assert.equal(MockRemoteAPI.requests[2].url, MockData.recentBuildsUrl('some builder 2', 2)); 1082 MockRemoteAPI.requests[2].resolve({}); 1083 MockRemoteAPI.reset(); 1084 await MockRemoteAPI.waitForRequest(); 1085 1086 assert.equal(MockRemoteAPI.requests.length, 3); 1087 assert.equal(MockRemoteAPI.requests[0].method, 'GET'); 1088 assert.equal(MockRemoteAPI.requests[0].url, MockData.pendingBuildsUrl('some tester')); 1089 MockRemoteAPI.requests[0].resolve({}); 1090 assert.equal(MockRemoteAPI.requests[1].method, 'GET'); 1091 assert.equal(MockRemoteAPI.requests[1].url, MockData.pendingBuildsUrl('some-builder-1')); 1092 MockRemoteAPI.requests[1].resolve({}); 1093 assert.equal(MockRemoteAPI.requests[2].method, 'GET'); 1094 assert.equal(MockRemoteAPI.requests[2].url, MockData.pendingBuildsUrl('some builder 2')); 1095 MockRemoteAPI.requests[2].resolve({}); 1096 MockRemoteAPI.reset(); 1097 await MockRemoteAPI.waitForRequest(); 1098 1099 assert.equal(MockRemoteAPI.requests.length, 3); 1100 assert.equal(MockRemoteAPI.requests[0].method, 'GET'); 1101 assert.equal(MockRemoteAPI.requests[0].url, MockData.recentBuildsUrl('some tester', 2)); 1102 MockRemoteAPI.requests[0].resolve({}); 1103 assert.equal(MockRemoteAPI.requests[1].method, 'GET'); 1104 assert.equal(MockRemoteAPI.requests[1].url, MockData.recentBuildsUrl('some-builder-1', 2)); 1105 MockRemoteAPI.requests[1].resolve({'builds': [MockData.runningBuildData({buildRequestId: 801}), MockData.finishedBuildData({buildRequestId: 800})]}); 1106 assert.equal(MockRemoteAPI.requests[2].method, 'GET'); 1107 assert.equal(MockRemoteAPI.requests[2].url, MockData.recentBuildsUrl('some builder 2', 2)); 1108 MockRemoteAPI.requests[2].resolve({}); 1109 MockRemoteAPI.reset(); 1110 1111 await syncPromise; 1112 await BuildRequest.fetchForTriggerable(MockData.mockTestSyncConfigWithPatchAcceptingBuilder().triggerableName); 1113 assert.equal(BuildRequest.all().length, 8); 1114 buildRequest = BuildRequest.findById(800); 1115 anotherBuildRequest = BuildRequest.findById(900); 1116 assert.equal(buildRequest.status(), 'failed'); 1117 assert.equal(anotherBuildRequest.status(), 'pending'); 1118 assert.equal(buildRequest.statusUrl(), MockData.statusUrl('some-builder-1', 123)); 1119 assert.equal(anotherBuildRequest.statusUrl(), null); 1120 1121 const secondSyncPromise = triggerable.initSyncers().then(() => triggerable.syncOnce()); 1122 assertRequestAndResolve(MockRemoteAPI.requests[0], 'GET', MockData.buildbotBuildersURL(), MockData.mockBuildbotBuilders()); 1123 MockRemoteAPI.reset(); 1124 await MockRemoteAPI.waitForRequest(); 1125 1126 assert.equal(MockRemoteAPI.requests.length, 3); 1127 assert.equal(MockRemoteAPI.requests[0].method, 'GET'); 1128 assert.equal(MockRemoteAPI.requests[0].url, MockData.pendingBuildsUrl('some tester')); 1129 MockRemoteAPI.requests[0].resolve({}); 1130 assert.equal(MockRemoteAPI.requests[1].method, 'GET'); 1131 assert.equal(MockRemoteAPI.requests[1].url, MockData.pendingBuildsUrl('some-builder-1')); 1132 MockRemoteAPI.requests[1].resolve({}); 1133 assert.equal(MockRemoteAPI.requests[2].method, 'GET'); 1134 assert.equal(MockRemoteAPI.requests[2].url, MockData.pendingBuildsUrl('some builder 2')); 1135 MockRemoteAPI.requests[2].resolve({}); 1136 MockRemoteAPI.reset(); 1137 await MockRemoteAPI.waitForRequest(); 1138 1139 assert.equal(MockRemoteAPI.requests.length, 3); 1140 assert.equal(MockRemoteAPI.requests[0].method, 'GET'); 1141 assert.equal(MockRemoteAPI.requests[0].url, MockData.recentBuildsUrl('some tester', 2)); 1142 MockRemoteAPI.requests[0].resolve({}); 1143 assert.equal(MockRemoteAPI.requests[1].method, 'GET'); 1144 assert.equal(MockRemoteAPI.requests[1].url, MockData.recentBuildsUrl('some-builder-1', 2)); 1145 MockRemoteAPI.requests[1].resolve({'builds': [MockData.runningBuildData({buildRequestId: 801})]}); 1146 assert.equal(MockRemoteAPI.requests[2].method, 'GET'); 1147 assert.equal(MockRemoteAPI.requests[2].url, MockData.recentBuildsUrl('some builder 2', 2)); 1148 MockRemoteAPI.requests[2].resolve({}); 1149 MockRemoteAPI.reset(); 1150 await MockRemoteAPI.waitForRequest(); 1151 1152 assert.equal(MockRemoteAPI.requests.length, 1); 1153 assert.equal(MockRemoteAPI.requests[0].method, 'POST'); 1154 assert.equal(MockRemoteAPI.requests[0].url, '/api/v2/forceschedulers/force-some-builder-2'); 1155 assert.deepEqual(MockRemoteAPI.requests[0].data, {'id': 900, 'jsonrpc': '2.0', 'method': 'force', 'params': 1156 {'wk': '191622', 'os': '10.11 15A284', 'wk-patch': 'http://localhost:8180/api/uploaded-file/100.txt', 1157 'build-request-id': '900', 'forcescheduler': 'force-some-builder-2'}}); 1158 }); 1159 1160 it('should not reuse the root when a build request with same commit set is avaialble but the build request has been scheduled', async () => { 1161 await MockData.addMockBuildRequestsWithRoots(TestServer.database()); 1162 await Manifest.fetch(); 1163 const config = MockData.mockTestSyncConfigWithPatchAcceptingBuilder(); 1164 const logger = new MockLogger; 1165 const slaveInfo = {name: 'sync-slave', password: 'password'}; 1166 const triggerable = new BuildbotTriggerable(config, TestServer.remoteAPI(), MockRemoteAPI, slaveInfo, logger); 1167 const syncPromise = triggerable.initSyncers().then(() => triggerable.syncOnce()); 1168 assertRequestAndResolve(MockRemoteAPI.requests[0], 'GET', MockData.buildbotBuildersURL(), MockData.mockBuildbotBuilders()); 1169 MockRemoteAPI.reset(); 1170 await MockRemoteAPI.waitForRequest(); 1171 1172 assert.equal(BuildRequest.all().length, 8); 1173 let buildRequest = BuildRequest.findById(800); 1174 let anotherBuildRequest = BuildRequest.findById(900); 1175 assert.equal(buildRequest.status(), 'completed'); 1176 assert.equal(anotherBuildRequest.status(), 'pending'); 1177 assert.equal(buildRequest.statusUrl(), 'http://build.webkit.org/buids/1'); 1178 assert.equal(anotherBuildRequest.statusUrl(), null); 1179 let commitSet = buildRequest.commitSet(); 1180 let anotherCommitSet = anotherBuildRequest.commitSet(); 1181 assert.ok(commitSet.equalsIgnoringRoot(anotherCommitSet)); 1182 assert.ok(!commitSet.equals(anotherCommitSet)); 1183 1184 assert.equal(MockRemoteAPI.requests.length, 3); 1185 assert.equal(MockRemoteAPI.requests[0].method, 'GET'); 1186 assert.equal(MockRemoteAPI.requests[0].url, MockData.pendingBuildsUrl('some tester')); 1187 MockRemoteAPI.requests[0].resolve({}); 1188 assert.equal(MockRemoteAPI.requests[1].method, 'GET'); 1189 assert.equal(MockRemoteAPI.requests[1].url, MockData.pendingBuildsUrl('some-builder-1')); 1190 MockRemoteAPI.requests[1].resolve({}); 1191 assert.equal(MockRemoteAPI.requests[2].method, 'GET'); 1192 assert.equal(MockRemoteAPI.requests[2].url, MockData.pendingBuildsUrl('some builder 2')); 1193 MockRemoteAPI.requests[2].resolve({}); 1194 MockRemoteAPI.reset(); 1195 await MockRemoteAPI.waitForRequest(); 1196 1197 assert.equal(MockRemoteAPI.requests.length, 3); 1198 assert.equal(MockRemoteAPI.requests[0].method, 'GET'); 1199 assert.equal(MockRemoteAPI.requests[0].url, MockData.recentBuildsUrl('some tester', 2)); 1200 MockRemoteAPI.requests[0].resolve({}); 1201 assert.equal(MockRemoteAPI.requests[1].method, 'GET'); 1202 assert.equal(MockRemoteAPI.requests[1].url, MockData.recentBuildsUrl('some-builder-1', 2)); 1203 MockRemoteAPI.requests[1].resolve({'builds': [MockData.runningBuildData({buildRequestId: 801}), MockData.finishedBuildData({buildRequestId: 800})]}); 1204 assert.equal(MockRemoteAPI.requests[2].method, 'GET'); 1205 assert.equal(MockRemoteAPI.requests[2].url, MockData.recentBuildsUrl('some builder 2', 2)); 1206 MockRemoteAPI.requests[2].resolve({}); 1207 MockRemoteAPI.reset(); 1208 await MockRemoteAPI.waitForRequest(); 1209 1210 assert.equal(MockRemoteAPI.requests.length, 3); 1211 assert.equal(MockRemoteAPI.requests[0].method, 'GET'); 1212 assert.equal(MockRemoteAPI.requests[0].url, MockData.pendingBuildsUrl('some tester')); 1213 MockRemoteAPI.requests[0].resolve({}); 1214 assert.equal(MockRemoteAPI.requests[1].method, 'GET'); 1215 assert.equal(MockRemoteAPI.requests[1].url, MockData.pendingBuildsUrl('some-builder-1')); 1216 MockRemoteAPI.requests[1].resolve({}); 1217 assert.equal(MockRemoteAPI.requests[2].method, 'GET'); 1218 assert.equal(MockRemoteAPI.requests[2].url, MockData.pendingBuildsUrl('some builder 2')); 1219 MockRemoteAPI.requests[2].resolve({}); 1220 MockRemoteAPI.reset(); 1221 await MockRemoteAPI.waitForRequest(); 1222 1223 assert.equal(MockRemoteAPI.requests.length, 3); 1224 assert.equal(MockRemoteAPI.requests[0].method, 'GET'); 1225 assert.equal(MockRemoteAPI.requests[0].url, MockData.recentBuildsUrl('some tester', 2)); 1226 MockRemoteAPI.requests[0].resolve({}); 1227 assert.equal(MockRemoteAPI.requests[1].method, 'GET'); 1228 assert.equal(MockRemoteAPI.requests[1].url, MockData.recentBuildsUrl('some-builder-1', 2)); 1229 MockRemoteAPI.requests[1].resolve({'builds': [MockData.runningBuildData({buildRequestId: 801}), MockData.finishedBuildData({buildRequestId: 800})]}); 1230 assert.equal(MockRemoteAPI.requests[2].method, 'GET'); 1231 assert.equal(MockRemoteAPI.requests[2].url, MockData.recentBuildsUrl('some builder 2', 2)); 1232 MockRemoteAPI.requests[2].resolve({'builds': [MockData.runningBuildData({buildRequestId: 900, builderId: 3})]}); 1233 MockRemoteAPI.reset(); 1234 1235 await syncPromise; 1236 await BuildRequest.fetchForTriggerable(MockData.mockTestSyncConfigWithPatchAcceptingBuilder().triggerableName); 1237 assert.equal(BuildRequest.all().length, 8); 1238 buildRequest = BuildRequest.findById(800); 1239 anotherBuildRequest = BuildRequest.findById(900); 1240 assert.equal(buildRequest.status(), 'completed'); 1241 assert.equal(anotherBuildRequest.status(), 'running'); 1242 assert.equal(buildRequest.statusUrl(), 'http://build.webkit.org/buids/1'); 1243 assert.equal(anotherBuildRequest.statusUrl(), 'http://build.webkit.org/#/builders/3/builds/124'); 948 1244 }); 949 1245 }); -
trunk/Websites/perf.webkit.org/tools/js/buildbot-triggerable.js
r250465 r269871 78 78 } 79 79 80 syncOnce() 81 { 82 let syncerList = this._syncers; 83 let buildReqeustsByGroup = new Map; 84 80 async syncOnce() 81 { 85 82 this._logger.log(`Fetching build requests for ${this._name}...`); 86 let validRequests; 87 return BuildRequest.fetchForTriggerable(this._name).then((buildRequests) => { 88 validRequests = this._validateRequests(buildRequests); 89 buildReqeustsByGroup = BuildbotTriggerable._testGroupMapForBuildRequests(buildRequests); 90 return this._pullBuildbotOnAllSyncers(buildReqeustsByGroup); 91 }).then((updates) => { 92 this._logger.log('Scheduling builds'); 93 const promistList = []; 94 const testGroupList = Array.from(buildReqeustsByGroup.values()).sort(function (a, b) { return a.groupOrder - b.groupOrder; }); 95 for (const group of testGroupList) { 96 const nextRequest = this._nextRequestInGroup(group, updates); 97 if (!validRequests.has(nextRequest)) 98 continue; 99 const promise = this._scheduleRequestIfSlaveIsAvailable(nextRequest, group.requests, 100 nextRequest.isBuild() ? group.buildSyncer : group.testSyncer, 101 nextRequest.isBuild() ? group.buildSlaveName : group.testSlaveName); 102 if (promise) 103 promistList.push(promise); 104 } 105 return Promise.all(promistList); 106 }).then(() => { 107 // Pull all buildbots for the second time since the previous step may have scheduled more builds. 108 return this._pullBuildbotOnAllSyncers(buildReqeustsByGroup); 109 }).then((updates) => { 110 // FIXME: Add a new API that just updates the requests. 111 return this._remote.postJSONWithStatus(`/api/build-requests/${this._name}`, { 112 'slaveName': this._slaveInfo.name, 113 'slavePassword': this._slaveInfo.password, 114 'buildRequestUpdates': updates}); 115 }); 83 84 const buildRequests = await BuildRequest.fetchForTriggerable(this._name); 85 const validRequests = this._validateRequests(buildRequests); 86 const buildReqeustsByGroup = BuildbotTriggerable._testGroupMapForBuildRequests(buildRequests); 87 let updates = await this._pullBuildbotOnAllSyncers(buildReqeustsByGroup); 88 let rootReuseUpdates = {} 89 this._logger.log('Scheduling builds'); 90 const promiseList = []; 91 const testGroupList = Array.from(buildReqeustsByGroup.values()).sort(function (a, b) { return a.groupOrder - b.groupOrder; }); 92 93 await Promise.all(testGroupList.map((group) => [group, this._nextRequestInGroup(group, updates)]) 94 .filter(([group, request]) => validRequests.has(request)) 95 .map(([group, request]) => this._scheduleRequest(group, request, rootReuseUpdates))); 96 97 // Pull all buildbots for the second time since the previous step may have scheduled more builds 98 updates = await this._pullBuildbotOnAllSyncers(buildReqeustsByGroup); 99 100 // rootReuseUpdates will be overridden by status fetched from buildbot. 101 updates = { 102 ...rootReuseUpdates, 103 ...updates 104 }; 105 return await this._remote.postJSONWithStatus(`/api/build-requests/${this._name}`, { 106 'slaveName': this._slaveInfo.name, 107 'slavePassword': this._slaveInfo.password, 108 'buildRequestUpdates': updates}); 109 } 110 111 async _scheduleRequest(testGroup, buildRequest, updates) 112 { 113 const buildRequestForRootReuse = await buildRequest.findBuildRequestWithSameRoots(); 114 if (buildRequestForRootReuse) { 115 if (!buildRequestForRootReuse.hasCompleted()) { 116 this._logger.log(`Found build request ${buildRequestForRootReuse.id()} is building the same root, will wait until it finishes.`); 117 return; 118 } 119 120 this._logger.log(`Will reuse existing root built from ${buildRequestForRootReuse.id()} for ${buildRequest.id()}`); 121 updates[buildRequest.id()] = {status: 'completed', url: buildRequestForRootReuse.statusUrl(), 122 statusDescription: buildRequestForRootReuse.statusDescription(), 123 buildRequestForRootReuse: buildRequestForRootReuse.id()}; 124 return; 125 } 126 127 return await this._scheduleRequestIfSlaveIsAvailable(buildRequest, testGroup.requests, 128 buildRequest.isBuild() ? testGroup.buildSyncer : testGroup.testSyncer, 129 buildRequest.isBuild() ? testGroup.buildSlaveName : testGroup.testSlaveName); 116 130 } 117 131 -
trunk/Websites/perf.webkit.org/unit-tests/build-request-tests.js
r225898 r269871 4 4 5 5 require('../tools/js/v3-models.js'); 6 let MockModels = require('./resources/mock-v3-models.js').MockModels; 6 const MockModels = require('./resources/mock-v3-models.js').MockModels; 7 const NodePrivilegedAPI = require('../tools/js/privileged-api.js').PrivilegedAPI; 8 const MockRemoteAPI = require('./resources/mock-remote-api.js').MockRemoteAPI; 7 9 8 10 function sampleBuildRequestData() … … 57 59 } 58 60 61 function oneTestGroup() 62 { 63 return { 64 "testGroups": [{ 65 "id": "2128", 66 "task": "1376", 67 "platform": "31", 68 "name": "Confirm", 69 "author": "rniwa", 70 "createdAt": 1458688514000, 71 "hidden": false, 72 "needsNotification": true, 73 "buildRequests": ["16985", "16986", "16987", "16988"], 74 "commitSets": ["4255", "4256"], 75 "notificationSentAt": null, 76 'initialRepetitionCount': 1 77 }], 78 "buildRequests": [{ 79 "id": "16985", 80 "triggerable": "3", 81 "task": "1376", 82 "test": "844", 83 "platform": "31", 84 "testGroup": "2128", 85 "order": "-2", 86 "commitSet": "4255", 87 "status": "pending", 88 "url": null, 89 "build": null, 90 "createdAt": 1458688514000 91 }, { 92 "id": "16986", 93 "triggerable": "3", 94 "task": "1376", 95 "test": "844", 96 "platform": "31", 97 "testGroup": "2128", 98 "order": "-1", 99 "commitSet": "4256", 100 "status": "pending", 101 "url": null, 102 "build": null, 103 "createdAt": 1458688514000 104 }, { 105 "id": "16987", 106 "triggerable": "3", 107 "task": "1376", 108 "test": "844", 109 "platform": "31", 110 "testGroup": "2128", 111 "order": "0", 112 "commitSet": "4255", 113 "status": "pending", 114 "url": null, 115 "build": null, 116 "createdAt": 1458688514000 117 }, { 118 "id": "16988", 119 "triggerable": "3", 120 "task": "1376", 121 "test": "844", 122 "platform": "31", 123 "testGroup": "2128", 124 "order": "3", 125 "commitSet": "4256", 126 "status": "pending", 127 "url": null, 128 "build": null, 129 "createdAt": 1458688514000 130 }], 131 "commitSets": [{ 132 "id": "4255", 133 "revisionItems": [{"commit": "87832"}, {"commit": "93116"}], 134 "customRoots": [], 135 }, { 136 "id": "4256", 137 "revisionItems": [{"commit": "87832"}, {"commit": "96336"}], 138 "customRoots": [], 139 }], 140 "commits": [{ 141 "id": "87832", 142 "repository": "9", 143 "revision": "10.11 15A284", 144 "time": 0 145 }, { 146 "id": "93116", 147 "repository": "11", 148 "revision": "191622", 149 "time": 1445945816878 150 }, { 151 "id": "87832", 152 "repository": "9", 153 "revision": "10.11 15A284", 154 "time": 0 155 }, { 156 "id": "96336", 157 "repository": "11", 158 "revision": "192736", 159 "time": 1448225325650 160 }], 161 "uploadedFiles": [], 162 "status": "OK" 163 }; 164 } 165 166 function threeTestGroups(secondTestGroupOverrides, thirdTestGroupOverrides) 167 { 168 if (!secondTestGroupOverrides) 169 secondTestGroupOverrides = {}; 170 if (!thirdTestGroupOverrides) 171 thirdTestGroupOverrides = {}; 172 return { 173 "testGroups": [{ 174 "id": "2128", 175 "task": "1376", 176 "platform": "32", 177 "name": "Confirm", 178 "author": "rniwa", 179 "createdAt": 1458688514000, 180 "hidden": false, 181 "needsNotification": true, 182 "buildRequests": ["16985", "16986", "16987", "16988"], 183 "commitSets": ["4255", "4256"], 184 "notificationSentAt": null, 185 'initialRepetitionCount': 1 186 }, { 187 "id": "2129", 188 "task": secondTestGroupOverrides.task || '1376', 189 "platform": secondTestGroupOverrides.platform || '32', 190 "name": "Confirm", 191 "author": "rniwa", 192 "createdAt": 1458688514000, 193 "hidden": false, 194 "needsNotification": true, 195 "buildRequests": ["16989", "16990", "16991", "16992"], 196 "commitSets": ["4255", "4256"], 197 "notificationSentAt": null, 198 'initialRepetitionCount': 1 199 }, { 200 "id": "2130", 201 "task": thirdTestGroupOverrides.task || '1376', 202 "platform": thirdTestGroupOverrides.platform || '32', 203 "name": "Confirm", 204 "author": "rniwa", 205 "createdAt": 1458688514000, 206 "hidden": false, 207 "needsNotification": true, 208 "buildRequests": ["16993", "16994", "16995", "16996"], 209 "commitSets": ["4255", "4256"], 210 "notificationSentAt": null, 211 'initialRepetitionCount': 1 212 }], 213 "buildRequests": [{ 214 "id": "16985", 215 "triggerable": "3", 216 "task": "1376", 217 "test": "844", 218 "platform": "32", 219 "testGroup": "2128", 220 "order": "-2", 221 "commitSet": "4255", 222 "status": "pending", 223 "url": null, 224 "build": null, 225 "createdAt": 1458688514000 226 }, { 227 "id": "16986", 228 "triggerable": "3", 229 "task": "1376", 230 "test": "844", 231 "platform": "32", 232 "testGroup": "2128", 233 "order": "-1", 234 "commitSet": "4256", 235 "status": "pending", 236 "url": null, 237 "build": null, 238 "createdAt": 1458688514000 239 }, { 240 "id": "16987", 241 "triggerable": "3", 242 "task": "1376", 243 "test": "844", 244 "platform": "32", 245 "testGroup": "2128", 246 "order": "0", 247 "commitSet": "4255", 248 "status": "pending", 249 "url": null, 250 "build": null, 251 "createdAt": 1458688514000 252 }, { 253 "id": "16988", 254 "triggerable": "3", 255 "task": "1376", 256 "test": "844", 257 "platform": "32", 258 "testGroup": "2128", 259 "order": "1", 260 "commitSet": "4256", 261 "status": "pending", 262 "url": null, 263 "build": null, 264 "createdAt": 1458688514000 265 }, { 266 "id": "16989", 267 "triggerable": "3", 268 "task": secondTestGroupOverrides.task || '1376', 269 "test": "844", 270 "platform": secondTestGroupOverrides.platform || '32', 271 "testGroup": "2129", 272 "order": "-2", 273 "commitSet": "4255", 274 "status": secondTestGroupOverrides.status && secondTestGroupOverrides.status[0] || 'pending', 275 "url": null, 276 "build": null, 277 "createdAt": 1458688514000 278 }, { 279 "id": "16990", 280 "triggerable": "3", 281 "task": secondTestGroupOverrides.task || '1376', 282 "test": "844", 283 "platform": secondTestGroupOverrides.platform || '32', 284 "testGroup": "2129", 285 "order": "-1", 286 "commitSet": "4256", 287 "status": secondTestGroupOverrides.status && secondTestGroupOverrides.status[1] || 'pending', 288 "url": null, 289 "build": null, 290 "createdAt": 1458688514000 291 }, { 292 "id": "16991", 293 "triggerable": "3", 294 "task": secondTestGroupOverrides.task || '1376', 295 "test": "844", 296 "platform": secondTestGroupOverrides.platform || '32', 297 "testGroup": "2129", 298 "order": "0", 299 "commitSet": "4255", 300 "status": secondTestGroupOverrides.status && secondTestGroupOverrides.status[2] || 'pending', 301 "url": null, 302 "build": null, 303 "createdAt": 1458688514000 304 }, { 305 "id": "16992", 306 "triggerable": "3", 307 "task": secondTestGroupOverrides.task || '1376', 308 "test": "844", 309 "platform": secondTestGroupOverrides.platform || '32', 310 "testGroup": "2129", 311 "order": "3", 312 "commitSet": "4256", 313 "status": secondTestGroupOverrides.status && secondTestGroupOverrides.status[3] || 'pending', 314 "url": null, 315 "build": null, 316 "createdAt": 1458688514000 317 }, { 318 "id": "16993", 319 "triggerable": "3", 320 "task": thirdTestGroupOverrides.task || '1376', 321 "test": "844", 322 "platform": thirdTestGroupOverrides.platform || '32', 323 "testGroup": "2130", 324 "order": "-2", 325 "commitSet": "4255", 326 "status": thirdTestGroupOverrides.status && thirdTestGroupOverrides.status[0] || 'pending', 327 "url": null, 328 "build": null, 329 "createdAt": 1458688513000 330 }, { 331 "id": "16994", 332 "triggerable": "3", 333 "task": thirdTestGroupOverrides.task || '1376', 334 "test": "844", 335 "platform": thirdTestGroupOverrides.platform || '32', 336 "testGroup": "2130", 337 "order": "-1", 338 "commitSet": "4256", 339 "status": thirdTestGroupOverrides.status && thirdTestGroupOverrides.status[1] || 'pending', 340 "url": null, 341 "build": null, 342 "createdAt": 1458688514000 343 }, { 344 "id": "16995", 345 "triggerable": "3", 346 "task": thirdTestGroupOverrides.task || '1376', 347 "test": "844", 348 "platform": thirdTestGroupOverrides.platform || '32', 349 "testGroup": "2130", 350 "order": "0", 351 "commitSet": "4255", 352 "status": thirdTestGroupOverrides.status && thirdTestGroupOverrides.status[2] || 'pending', 353 "url": null, 354 "build": null, 355 "createdAt": 1458688514000 356 }, { 357 "id": "16996", 358 "triggerable": "3", 359 "task": secondTestGroupOverrides.task || '1376', 360 "test": "844", 361 "platform": secondTestGroupOverrides.platform || '32', 362 "testGroup": "2130", 363 "order": "1", 364 "commitSet": "4256", 365 "status": thirdTestGroupOverrides.status && thirdTestGroupOverrides.status[3] || 'pending', 366 "url": null, 367 "build": null, 368 "createdAt": 1458688514000 369 }], 370 "commitSets": [{ 371 "id": "4255", 372 "revisionItems": [{"commit": "87832"}, {"commit": "93116"}], 373 "customRoots": [], 374 }, { 375 "id": "4256", 376 "revisionItems": [{"commit": "87832"}, {"commit": "96336"}], 377 "customRoots": [], 378 }], 379 "commits": [{ 380 "id": "87832", 381 "repository": "9", 382 "revision": "10.11 15A284", 383 "time": 0 384 }, { 385 "id": "93116", 386 "repository": "11", 387 "revision": "191622", 388 "time": 1445945816878 389 }, { 390 "id": "87832", 391 "repository": "9", 392 "revision": "10.11 15A284", 393 "time": 0 394 }, { 395 "id": "96336", 396 "repository": "11", 397 "revision": "192736", 398 "time": 1448225325650 399 }], 400 "uploadedFiles": [], 401 "status": "OK" 402 }; 403 } 404 59 405 describe('BuildRequest', function () { 60 406 MockModels.inject(); 407 408 describe('findBuildRequestWithSameRoots', () => { 409 const requests = MockRemoteAPI.inject('https://perf.webkit.org'); 410 411 it('should return null when the build request is not build type build request', async () => { 412 const data = sampleBuildRequestData(); 413 const request = BuildRequest.constructBuildRequestsFromData(data)[0]; 414 const result = await request.findBuildRequestWithSameRoots(); 415 assert.equal(result, null); 416 }); 417 418 it('should return null if this there is no other test group under current analysis task', async () => { 419 const data = oneTestGroup(); 420 const platformId = data.buildRequests[0].platform; 421 Platform.ensureSingleton(platformId, {id: platformId, metrics: [], name: 'some platform'}); 422 const request = BuildRequest.constructBuildRequestsFromData(data)[0]; 423 const promise = request.findBuildRequestWithSameRoots(); 424 assert.equal(requests.length, 1); 425 426 assert.equal(requests[0].url, '/api/test-groups?task=1376'); 427 assert.equal(requests[0].method, 'GET'); 428 requests[0].resolve(oneTestGroup()); 429 430 const result = await promise; 431 assert.equal(result, null); 432 }); 433 434 it('should return completed build request if a completed reusable build request found', async () => { 435 const overrides = { 436 task: '1376', 437 platform: '32', 438 status: ['completed', 'pending', 'pending', 'pending'] 439 } 440 const data = threeTestGroups(overrides); 441 const platformId = data.buildRequests[0].platform; 442 Platform.ensureSingleton(platformId, {id: platformId, metrics: [], name: 'some platform'}); 443 const request = BuildRequest.constructBuildRequestsFromData(data)[0]; 444 const promise = request.findBuildRequestWithSameRoots(); 445 assert.equal(requests.length, 1); 446 447 assert.equal(requests[0].url, '/api/test-groups?task=1376'); 448 assert.equal(requests[0].method, 'GET'); 449 requests[0].resolve(threeTestGroups(overrides)); 450 451 const result = await promise; 452 assert.equal(result, BuildRequest.findById(16989)) 453 }); 454 455 it('should not use cache while fetching test groups under analysis task', async () => { 456 const overrides = { 457 task: '1376', 458 platform: '32', 459 status: ['completed', 'pending', 'pending', 'pending'] 460 }; 461 const data = threeTestGroups(overrides); 462 const platformId = data.buildRequests[0].platform; 463 Platform.ensureSingleton(platformId, {id: platformId, metrics: [], name: 'some platform'}); 464 const request = BuildRequest.constructBuildRequestsFromData(data)[0]; 465 let promise = request.findBuildRequestWithSameRoots(); 466 assert.equal(requests.length, 1); 467 468 assert.equal(requests[0].url, '/api/test-groups?task=1376'); 469 assert.equal(requests[0].method, 'GET'); 470 requests[0].resolve(threeTestGroups(overrides)); 471 472 let result = await promise; 473 assert.equal(result, BuildRequest.findById(16989)) 474 475 MockRemoteAPI.reset(); 476 promise = request.findBuildRequestWithSameRoots(); 477 assert.equal(requests.length, 1); 478 479 assert.equal(requests[0].url, '/api/test-groups?task=1376'); 480 assert.equal(requests[0].method, 'GET'); 481 requests[0].resolve(threeTestGroups(overrides)); 482 483 result = await promise; 484 assert.equal(result, BuildRequest.findById(16989)) 485 }); 486 487 it('should only allow identical platform if the platform is not under a platform group', async () => { 488 const overrides = { 489 task: '1376', 490 platform: '33', 491 status: ['completed', 'pending', 'pending', 'pending'] 492 }; 493 const data = threeTestGroups(overrides); 494 const platformId = data.buildRequests[0].platform; 495 Platform.ensureSingleton(platformId, {id: platformId, metrics: [], name: 'some platform'}); 496 Platform.ensureSingleton('33', {id: '33', metrics: [], name: 'another platform'}); 497 const request = BuildRequest.constructBuildRequestsFromData(data)[0]; 498 const promise = request.findBuildRequestWithSameRoots(); 499 assert.equal(requests.length, 1); 500 501 assert.equal(requests[0].url, '/api/test-groups?task=1376'); 502 assert.equal(requests[0].method, 'GET'); 503 requests[0].resolve(threeTestGroups(overrides)); 504 505 const result = await promise; 506 assert.equal(result, null); 507 }); 508 509 it('should allow different platform if the platforms are under the same platform group', async () => { 510 const overrides = { 511 task: '1376', 512 platform: '33', 513 status: ['completed', 'pending', 'pending', 'pending'] 514 }; 515 const data = threeTestGroups(overrides); 516 const platformId = data.buildRequests[0].platform; 517 const platformGroup = PlatformGroup.ensureSingleton('1', {id: 1, name: 'some platform group'}); 518 Platform.ensureSingleton(platformId, {id: platformId, metrics: [], name: 'some platform', group: platformGroup}); 519 Platform.ensureSingleton('33', {id: '33', metrics: [], name: 'another platform', group: platformGroup}); 520 const request = BuildRequest.constructBuildRequestsFromData(data)[0]; 521 const promise = request.findBuildRequestWithSameRoots(); 522 assert.equal(requests.length, 1); 523 524 assert.equal(requests[0].url, '/api/test-groups?task=1376'); 525 assert.equal(requests[0].method, 'GET'); 526 requests[0].resolve(threeTestGroups(overrides)); 527 528 const result = await promise; 529 assert.equal(result, BuildRequest.findById(16989)) 530 }); 531 532 it('should in favor of running build request over scheduled build request', async () => { 533 const secondOverrides = { 534 task: '1376', 535 platform: '32', 536 status: ['scheduled', 'pending', 'pending', 'pending'] 537 }; 538 const thirdOverrides = { 539 task: '1376', 540 platform: '32', 541 status: ['running', 'pending', 'pending', 'pending'] 542 } 543 const data = threeTestGroups(secondOverrides, thirdOverrides); 544 const platformId = data.buildRequests[0].platform; 545 Platform.ensureSingleton(platformId, {id: platformId, metrics: [], name: 'some platform'}); 546 const request = BuildRequest.constructBuildRequestsFromData(data)[0]; 547 const promise = request.findBuildRequestWithSameRoots(); 548 assert.equal(requests.length, 1); 549 550 assert.equal(requests[0].url, '/api/test-groups?task=1376'); 551 assert.equal(requests[0].method, 'GET'); 552 requests[0].resolve(threeTestGroups(secondOverrides, thirdOverrides)); 553 554 const result = await promise; 555 assert.equal(result, BuildRequest.findById(16993)) 556 }); 557 558 it('should in favor of running build request which has earlier creation time', async () => { 559 const secondOverrides = { 560 task: '1376', 561 platform: '32', 562 status: ['running', 'pending', 'pending', 'pending'] 563 }; 564 const thirdOverrides = { 565 task: '1376', 566 platform: '32', 567 status: ['running', 'pending', 'pending', 'pending'] 568 } 569 const data = threeTestGroups(secondOverrides, thirdOverrides); 570 const platformId = data.buildRequests[0].platform; 571 Platform.ensureSingleton(platformId, {id: platformId, metrics: [], name: 'some platform'}); 572 const request = BuildRequest.constructBuildRequestsFromData(data)[0]; 573 const promise = request.findBuildRequestWithSameRoots(); 574 assert.equal(requests.length, 1); 575 576 assert.equal(requests[0].url, '/api/test-groups?task=1376'); 577 assert.equal(requests[0].method, 'GET'); 578 requests[0].resolve(threeTestGroups(secondOverrides, thirdOverrides)); 579 580 const result = await promise; 581 assert.equal(result, BuildRequest.findById(16993)); 582 assert.ok(BuildRequest.findById(16993).createdAt() < BuildRequest.findById(16989).createdAt()); 583 }); 584 }); 61 585 62 586 describe('waitingTime', function () {
Note: See TracChangeset
for help on using the changeset viewer.