+2017-05-10 Ryosuke Niwa <rniwa@webkit.org>
+
+ Add API to upload a patched build for a custom A/B testing
+ https://bugs.webkit.org/show_bug.cgi?id=171956
+
+ Reviewed by Chris Dumez.
+
+ Added /api/upload-root to upload a root file, the build product of a patch associated with a commit set.
+
+ Extracted more functions out of privileged-api/upload-file.php to uploaded-file-helpers.php to share code
+ with /api/upload-root.php.
+
+ * public/api/upload-root.php: Added.
+ (main):
+ (compute_commit_set_items_to_update): Find the list of commit set items to associate this root with.
+ A root can be associated with multiple repositories and there fore commit set items; e.g. if a software
+ is built from multiple repositories and there is a patch associated with one of them, the built product
+ must be associated with all those repositories.
+
+ * public/include/build-requests-fetcher.php:
+ (BuildRequestsFetcher::fetch_commits_for_set_if_needed): Include the root file is there is one.
+
+ * public/include/json-header.php:
+ (validate_arguments): Added the support for validating json string.
+ (verify_slave): Return the slave ID found.
+
+ * public/include/uploaded-file-helpers.php:
+ (validate_uploaded_file): Extracted from /privileged-api/upload-file to be shared with /api/upload-root.
+ (query_total_file_size): Ditto.
+ (create_uploaded_file_from_form_data): Ditto.
+ (upload_file_in_transaction): Ditto. Takes a lambda to do the extra work inside the transaction.
+
+ * public/privileged-api/upload-file.php:
+ (main):
+
+ * public/v3/models/build-request.js:
+ (BuildRequest.constructBuildRequestsFromData): Resolve the rootFIle of each commit set item.
+
+ * public/v3/models/commit-set.js:
+ (CommitSet): Added _repositoryToRootMap and _allRootFiles as instance variables.
+ (CommitSet.prototype.updateSingleton): Added. Previously, each commit set's states never changed after
+ its creation. After this patch, each item can be newly associated with a root so we must update its
+ _repositoryToRootMap and _allRootFiles. For simplicity, we update all states.
+ (CommitSet.prototype._updateFromObject): Extracted from the constructor.
+ (CommitSet.prototype.allRootFiles): Added. Includes custom roots and roots created for patches.
+ (CommitSet.prototype.rootForRepository): Added.
+ (CommitSet.prototype.equals): Fixed the bug that we were comparing _repositoryToPatchMap to
+ _repositoryToCommitMap, and added a check for _repositoryToRootMap.
+
+ * public/v3/models/test-group.js:
+ (TestGroup.prototype.task): Added.
+ (TestGroup.createWithTask):
+ (TestGroup.createWithCustomConfiguration):
+ (TestGroup.createAndRefetchTestGroups):
+ (TestGroup._fetchTestGroupsForTask): Deleted. Now fetchForTask takes a boolean argument: ignoreCache.
+ (TestGroup.findAllByTask): Added.
+ (TestGroup.fetchForTask): Renamed from fetchByTask.
+
+ * public/v3/pages/analysis-task-page.js:
+ (AnalysisTaskPage.prototype._fetchRelatedInfoForTaskId):
+
+ * server-tests/api-build-requests-tests.js:
+
+ * server-tests/api-upload-root-tests.js: Added. Added tests for /api/upload-root.
+ (makeReport): Added.
+ (addSlaveAndCreateRootFile): Added.
+ (createTestGroupWihPatch): Added.
+
+ * server-tests/privileged-api-create-test-group-tests.js:
+
+ * server-tests/resources/mock-data.js:
+ (MockData.sharedRepositoryId): Added.
+ (MockData.addMockData): Added "Shared" repository along with commits.
+
2017-05-10 Ryosuke Niwa <rniwa@webkit.org>
Rename server-tests/api-update-triggerable.js to server-tests/api-update-triggerable-tests.js
--- /dev/null
+<?php
+
+require_once('../include/json-header.php');
+require_once('../include/uploaded-file-helpers.php');
+
+function main()
+{
+ $input_file = validate_uploaded_file('rootFile');
+
+ $db = connect();
+ $slave_id = verify_slave($db, $_POST);
+
+ $arguments = validate_arguments($_POST, array(
+ 'builderName' => '/.+/',
+ 'buildNumber' => 'int',
+ 'buildTime' => '/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d*Z?$/',
+ 'buildRequest' => 'int',
+ 'repositoryList' => 'json',
+ ));
+ $build_request_id = $arguments['buildRequest'];
+
+ $request_row = $db->select_first_row('build_requests', 'request', array('id' => $build_request_id));
+ if ($request_row['request_test'] || $request_row['request_order'] >= 0)
+ exit_with_error('InvalidBuildRequestType', array('buildRequest' => $build_request_id));
+
+ $test_group = $db->select_first_row('analysis_test_groups', 'testgroup', array('id' => $request_row['request_group']));
+ assert($test_group);
+
+ $builder_id = $db->select_or_insert_row('builders', 'builder', array('name' => $arguments['builderName']));
+ $build_info = array('builder' => $builder_id, 'slave' => $slave_id, 'number' => $arguments['buildNumber'], 'time' => $arguments['buildTime']);
+
+ $commit_set_id = $request_row['request_commit_set'];
+ $commit_set_items_to_update = compute_commit_set_items_to_update($db, $commit_set_id, $arguments['repositoryList']);
+
+ $uploaded_file = upload_file_in_transaction($db, $input_file, $test_group['testgroup_author'],
+ function ($db, $file_row) use ($build_request_id, $build_info, $commit_set_id, $commit_set_items_to_update) {
+ $root_file_id = $file_row['file_id'];
+ // FIXME: Insert a build row and associated with the request.
+ $build_id = $db->insert_row('builds', 'build', $build_info);
+ if (!$build_id)
+ return array('status' => 'FailedToCreateBuild', 'build' => $build_info);
+ if (!$db->update_row('build_requests', 'request', array('id' => $build_request_id), array('status' => 'completed', 'build' => $build_id)))
+ return array('status' => 'FailedToUpdateBuildRequest', 'buildRequest' => $build_request_id);
+
+ foreach ($commit_set_items_to_update as $commit_id) {
+ if (!$db->update_row('commit_set_items', 'commitset',
+ array('set' => $commit_set_id, 'commit' => $commit_id),
+ array('commit' => $commit_id, 'root_file' => $root_file_id), '*'))
+ return array('status' => 'FailedToUpdateCommitSet', 'commitSet' => $commit_set_id, 'commit' => $commit_id);
+ }
+ return NULL;
+ });
+
+ exit_with_success(array('uploadedFile' => $uploaded_file));
+}
+
+function compute_commit_set_items_to_update($db, $commit_set_id, $repository_name_list)
+{
+ if (!is_array($repository_name_list))
+ exit_with_error('InvalidRepositoryList', array('repositoryList' => $repository_name_list));
+
+ $commit_repository_rows_in_set = $db->query_and_fetch_all('SELECT * FROM repositories, commits, commit_set_items
+ WHERE repository_id = commit_repository AND commit_id = commitset_commit
+ AND commitset_set = $1', array($commit_set_id));
+
+ $commit_by_repository_name = array();
+ if ($commit_repository_rows_in_set) {
+ foreach ($commit_repository_rows_in_set as $row)
+ $commit_by_repository_name[$row['repository_name']] = $row['commitset_commit'];
+ }
+
+ $commit_set_items_to_update = array();
+ foreach ($repository_name_list as $repository_name) {
+ $commit_id = array_get($commit_by_repository_name, $repository_name);
+ if (!$commit_id)
+ exit_with_error('InvalidRepository', array('repositoryName' => $repository_name, 'commitSet' => $commit_set_id));
+ array_push($commit_set_items_to_update, $commit_id);
+ }
+ if (!$commit_set_items_to_update)
+ exit_with_error('InvalidRepositoryList', array('repositoryList' => $repository_list));
+
+ return $commit_set_items_to_update;
+}
+
+main();
+
+?>
$patch_file_id = $row['commitset_patch_file'];
if ($patch_file_id)
$this->add_uploaded_file($patch_file_id);
- array_push($revision_items, array('commit' => $row['commit_id'], 'patch' => $patch_file_id));
+
+ $root_file_id = $row['commitset_root_file'];
+ if ($root_file_id)
+ $this->add_uploaded_file($root_file_id);
+
+ array_push($revision_items, array('commit' => $row['commit_id'], 'patch' => $patch_file_id, 'rootFile' => $root_file_id));
if (array_key_exists($commit_id, $this->commits_by_id))
continue;
} else if ($pattern == 'int?') {
require_format($name, $value, '/^\d*$/');
$value = $value ? intval($value) : null;
+ } else if ($pattern == 'json') {
+ $value = json_decode($value, true);
+ if ($value === NULL)
+ exit_with_error('Invalid' . camel_case_words_separated_by_underscore($name));
} else
require_format($name, $value, $pattern);
$result[$name] = $value;
$matched_slave = $db->select_first_row('build_slaves', 'slave', $slave_info);
if (!$matched_slave)
exit_with_error('SlaveNotFound', array('name' => $slave_info['name']));
+
+ return $matched_slave['slave_id'];
}
function find_triggerable_for_task($db, $task_id) {
<?php
+define('MEGABYTES', 1024 * 1024);
+
function format_uploaded_file($file_row)
{
return array(
return config_path('uploadDirectory', $file_row['file_id'] . $file_row['file_extension']);
}
+function validate_uploaded_file($field_name)
+{
+ if (array_get($_SERVER, 'CONTENT_LENGTH') && empty($_POST) && empty($_FILES))
+ exit_with_error('FileSizeLimitExceeded');
+
+ if (!is_dir(config_path('uploadDirectory', '')))
+ exit_with_error('NotSupported');
+
+ $input_file = array_get($_FILES, $field_name);
+ if (!$input_file)
+ exit_with_error('NoFileSpecified');
+
+ if ($input_file['error'] == UPLOAD_ERR_INI_SIZE || $input_file['error'] == UPLOAD_ERR_FORM_SIZE)
+ exit_with_error('FileSizeLimitExceeded');
+
+ if ($input_file['error'] != UPLOAD_ERR_OK)
+ exit_with_error('FailedToUploadFile', array('name' => $input_file['name'], 'error' => $input_file['error']));
+
+ if (config('uploadFileLimitInMB') * MEGABYTES < $input_file['size'])
+ exit_with_error('FileSizeLimitExceeded');
+
+ return $input_file;
+}
+
+function query_total_file_size($db, $user)
+{
+ if ($user)
+ $count_result = $db->query_and_fetch_all('SELECT sum(file_size) as "sum" FROM uploaded_files WHERE file_deleted_at IS NULL AND file_author = $1', array($user));
+ else
+ $count_result = $db->query_and_fetch_all('SELECT sum(file_size) as "sum" FROM uploaded_files WHERE file_deleted_at IS NULL AND file_author IS NULL');
+ if (!$count_result)
+ return FALSE;
+ return intval($count_result[0]["sum"]);
+}
+
+function create_uploaded_file_from_form_data($input_file)
+{
+ $file_sha256 = hash_file('sha256', $input_file['tmp_name']);
+ if (!$file_sha256)
+ exit_with_error('FailedToComputeSHA256');
+
+ $matches = array();
+ $file_extension = null;
+ if (preg_match('/(\.[a-zA-Z0-9]{1,5}){1,2}$/', $input_file['name'], $matches)) {
+ $file_extension = $matches[0];
+ assert(strlen($file_extension) <= 16);
+ }
+
+ return array(
+ 'author' => remote_user_name(),
+ 'filename' => $input_file['name'],
+ 'extension' => $file_extension,
+ 'mime' => $input_file['type'], // Sanitize MIME types.
+ 'size' => $input_file['size'],
+ 'sha256' => $file_sha256
+ );
+}
+
+function upload_file_in_transaction($db, $input_file, $remote_user, $additional_work = NULL)
+{
+ // FIXME: Cleanup old files.
+
+ if (config('uploadUserQuotaInMB') * MEGABYTES - query_total_file_size($db, $remote_user) < $input_file['size'])
+ exit_with_error('FileSizeQuotaExceeded');
+
+ $uploaded_file = create_uploaded_file_from_form_data($input_file);
+
+ $db->begin_transaction();
+ $file_row = $db->select_or_insert_row('uploaded_files', 'file',
+ array('sha256' => $uploaded_file['sha256'], 'deleted_at' => null), $uploaded_file, '*');
+ if (!$file_row)
+ exit_with_error('FailedToInsertFileData');
+
+ // A concurrent session may have inserted another file.
+ if (config('uploadUserQuotaInMB') * MEGABYTES < query_total_file_size($db, $remote_user)) {
+ $db->rollback_transaction();
+ exit_with_error('FileSizeQuotaExceeded');
+ }
+
+ if ($additional_work) {
+ $error = $additional_work($db, $file_row);
+ if ($error) {
+ $db->rollback_transaction();
+ exit_with_error($error['status'], $error);
+ }
+ }
+
+ $new_path = uploaded_file_path_for_row($file_row);
+ if (!move_uploaded_file($input_file['tmp_name'], $new_path)) {
+ $db->rollback_transaction();
+ exit_with_error('FailedToMoveUploadedFile');
+ }
+
+ $db->commit_transaction();
+
+ return format_uploaded_file($file_row);
+}
+
?>
<?php
-ini_set('upload_max_filesize', '1025M');
-ini_set('post_max_size', '1025M');
require_once('../include/json-header.php');
require_once('../include/uploaded-file-helpers.php');
-define('MEGABYTES', 1024 * 1024);
-
function main()
{
- if (array_get($_SERVER, 'CONTENT_LENGTH') && empty($_POST) && empty($_FILES))
- exit_with_error('FileSizeLimitExceeded');
+ $input_file = validate_uploaded_file('newFile');
if (!verify_token(array_get($_POST, 'token')))
exit_with_error('InvalidToken');
- if (!is_dir(config_path('uploadDirectory', '')))
- exit_with_error('NotSupported');
-
- $input_file = array_get($_FILES, 'newFile');
- if (!$input_file)
- exit_with_error('NoFileSpecified');
-
- if ($input_file['error'] == UPLOAD_ERR_INI_SIZE || $input_file['error'] == UPLOAD_ERR_FORM_SIZE)
- exit_with_error('FileSizeLimitExceeded');
-
- if ($input_file['error'] != UPLOAD_ERR_OK)
- exit_with_error('FailedToUploadFile', array('name' => $input_file['name'], 'error' => $input_file['error']));
-
- if (config('uploadFileLimitInMB') * MEGABYTES < $input_file['size'])
- exit_with_error('FileSizeLimitExceeded');
-
- $uploaded_file = create_uploaded_file_from_form_data($input_file);
-
$current_user = remote_user_name();
$db = connect();
- // FIXME: Cleanup old files.
-
- if (config('uploadUserQuotaInMB') * MEGABYTES - query_total_file_size($db, $current_user) < $input_file['size'])
- exit_with_error('FileSizeQuotaExceeded');
-
- $db->begin_transaction();
- $file_row = $db->select_or_insert_row('uploaded_files', 'file',
- array('sha256' => $uploaded_file['sha256'], 'deleted_at' => null), $uploaded_file, '*');
- if (!$file_row)
- exit_with_error('FailedToInsertFileData');
-
- // A concurrent session may have inserted another file.
- if (config('uploadUserQuotaInMB') * MEGABYTES < query_total_file_size($db, $current_user)) {
- $db->rollback_transaction();
- exit_with_error('FileSizeQuotaExceeded');
- }
-
- $new_path = uploaded_file_path_for_row($file_row);
- if (!move_uploaded_file($input_file['tmp_name'], $new_path)) {
- $db->rollback_transaction();
- exit_with_error('FailedToMoveUploadedFile');
- }
- $db->commit_transaction();
-
- exit_with_success(array('uploadedFile' => format_uploaded_file($file_row)));
-}
-
-function query_total_file_size($db, $user)
-{
- if ($user)
- $count_result = $db->query_and_fetch_all('SELECT sum(file_size) as "sum" FROM uploaded_files WHERE file_deleted_at IS NULL AND file_author = $1', array($user));
- else
- $count_result = $db->query_and_fetch_all('SELECT sum(file_size) as "sum" FROM uploaded_files WHERE file_deleted_at IS NULL AND file_author IS NULL');
- if (!$count_result)
- return FALSE;
- return intval($count_result[0]["sum"]);
-}
-
-function create_uploaded_file_from_form_data($input_file)
-{
- $file_sha256 = hash_file('sha256', $input_file['tmp_name']);
- if (!$file_sha256)
- exit_with_error('FailedToComputeSHA256');
-
- $matches = array();
- $file_extension = null;
- if (preg_match('/(\.[a-zA-Z0-9]{1,5}){1,2}$/', $input_file['name'], $matches)) {
- $file_extension = $matches[0];
- assert(strlen($file_extension) <= 16);
- }
+ $uploaded_file = upload_file_in_transaction($db, $input_file, $current_user);
- return array(
- 'author' => remote_user_name(),
- 'filename' => $input_file['name'],
- 'extension' => $file_extension,
- 'mime' => $input_file['type'], // Sanitize MIME types.
- 'size' => $input_file['size'],
- 'sha256' => $file_sha256
- );
+ exit_with_success(array('uploadedFile' => $uploaded_file));
}
main();
for (const item of rawData.revisionItems) {
item.commit = CommitLog.findById(item.commit);
item.patch = item.patch ? UploadedFile.findById(item.patch) : null;
+ item.rootFile = item.rootFile ? UploadedFile.findById(item.rootFile) : null;
}
rawData.customRoots = rawData.customRoots.map((fileId) => UploadedFile.findById(fileId));
return CommitSet.ensureSingleton(rawData.id, rawData);
this._repositories = [];
this._repositoryToCommitMap = new Map;
this._repositoryToPatchMap = new Map;
+ this._repositoryToRootMap = new Map;
this._latestCommitTime = null;
this._customRoots = [];
+ this._allRootFiles = [];
if (!object)
return;
+ this._updateFromObject(object);
+ }
+
+ updateSingleton(object)
+ {
+ this._repositoryToCommitMap.clear();
+ this._repositoryToPatchMap.clear();
+ this._repositoryToRootMap.clear();
+ this._repositories = [];
+ this._updateFromObject(object);
+ }
+
+ _updateFromObject(object)
+ {
+ const rootFiles = new Set;
for (const item of object.revisionItems) {
const commit = item.commit;
console.assert(commit instanceof CommitLog);
console.assert(!item.patch || item.patch instanceof UploadedFile);
+ console.assert(!item.rootFile || item.rootFile instanceof UploadedFile);
const repository = commit.repository();
this._repositoryToCommitMap.set(repository, commit);
this._repositoryToPatchMap.set(repository, item.patch);
+ this._repositoryToRootMap.set(repository, item.rootFile);
+ if (item.rootFile)
+ rootFiles.add(item.rootFile);
this._repositories.push(commit.repository());
}
this._customRoots = object.customRoots;
+ this._allRootFiles = Array.from(rootFiles).concat(object.customRoots);
}
repositories() { return this._repositories; }
customRoots() { return this._customRoots; }
+ allRootFiles() { return this._allRootFiles; }
commitForRepository(repository) { return this._repositoryToCommitMap.get(repository); }
revisionForRepository(repository)
}
patchForRepository(repository) { return this._repositoryToPatchMap.get(repository); }
+ rootForRepository(repository) { return this._repositoryToRootMap.get(repository); }
// FIXME: This should return a Date object.
latestCommitTime()
for (const [repository, commit] of this._repositoryToCommitMap) {
if (commit != other._repositoryToCommitMap.get(repository))
return false;
- if (this._repositoryToPatchMap.get(repository) != other._repositoryToCommitMap.get(repository))
+ if (this._repositoryToPatchMap.get(repository) != other._repositoryToPatchMap.get(repository))
+ return false;
+ if (this._repositoryToRootMap.get(repository) != other._repositoryToRootMap.get(repository))
return false;
}
return CommitSet.areCustomRootsEqual(this._customRoots, other._customRoots);
this._isHidden = object.hidden;
}
+ task() { return AnalysisTask.findById(this._taskId); }
createdAt() { return this._createdAt; }
isHidden() { return this._isHidden; }
buildRequests() { return this._buildRequests; }
return PrivilegedAPI.sendRequest('create-test-group', params).then((data) => {
return AnalysisTask.fetchById(data['taskId']);
}).then((task) => {
- return this._fetchTestGroupsForTask(task.id()).then(() => task);
+ return this.fetchForTask(task.id()).then(() => task);
});
}
const revisionSets = this._revisionSetsFromCommitSets(commitSets);
const params = {task: task.id(), name: groupName, platform: platform.id(), test: test.id(), repetitionCount, revisionSets};
return PrivilegedAPI.sendRequest('create-test-group', params).then((data) => {
- return this._fetchTestGroupsForTask(task.id());
+ return this.fetchForTask(task.id(), true);
});
}
name: name,
repetitionCount: repetitionCount,
revisionSets: revisionSets,
- }).then((data) => this._fetchTestGroupsForTask(task.id()));
+ }).then((data) => this.fetchForTask(task.id(), true));
}
static _revisionSetsFromCommitSets(commitSets)
});
}
- static _fetchTestGroupsForTask(taskId)
+ static findAllByTask(taskId)
{
- return this.cachedFetch('/api/test-groups', {task: taskId}, true).then((data) => this._createModelsFromFetchedTestGroups(data));
+ return TestGroup.all().filter((testGroup) => testGroup._taskId == taskId);
}
- static fetchByTask(taskId)
+ static fetchForTask(taskId, ignoreCache = false)
{
- return this.cachedFetch('/api/test-groups', {task: taskId}).then(this._createModelsFromFetchedTestGroups.bind(this));
+ return this.cachedFetch('/api/test-groups', {task: taskId}, ignoreCache).then(this._createModelsFromFetchedTestGroups.bind(this));
}
static _createModelsFromFetchedTestGroups(data)
_fetchRelatedInfoForTaskId(taskId)
{
- TestGroup.fetchByTask(taskId).then(this._didFetchTestGroups.bind(this));
+ TestGroup.fetchForTask(taskId).then(this._didFetchTestGroups.bind(this));
AnalysisResults.fetch(taskId).then(this._didFetchAnalysisResults.bind(this));
AnalysisTask.fetchRelatedTasks(taskId).then((relatedTasks) => {
this._relatedTasks = relatedTasks;
assert.equal(content['commitSets'].length, 2);
assert.equal(content['commitSets'][0].id, 401);
- assert.deepEqual(content['commitSets'][0].revisionItems, [{commit: '87832', patch: null}, {commit: '93116', patch: null}]);
+ assert.deepEqual(content['commitSets'][0].revisionItems,
+ [{commit: '87832', patch: null, rootFile: null}, {commit: '93116', patch: null, rootFile: null}]);
assert.equal(content['commitSets'][1].id, 402);
- assert.deepEqual(content['commitSets'][1].revisionItems, [{commit: '87832', patch: null}, {commit: '96336', patch: null}]);
+ assert.deepEqual(content['commitSets'][1].revisionItems,
+ [{commit: '87832', patch: null, rootFile: null}, {commit: '96336', patch: null, rootFile: null}]);
assert.equal(content['commits'].length, 3);
assert.equal(content['commits'][0].id, 87832);
assert.equal(content['commitSets'].length, 2);
assert.equal(content['commitSets'][0].id, 401);
assert.deepEqual(content['commitSets'][0].revisionItems,
- [{commit: '87832', patch: null}, {commit: '93116', patch: null}]);
+ [{commit: '87832', patch: null, rootFile: null}, {commit: '93116', patch: null, rootFile: null}]);
assert.equal(content['commitSets'][1].id, 402);
assert.deepEqual(content['commitSets'][1].revisionItems,
- [{commit: '87832', patch: null}, {commit: '96336', patch: null}]);
+ [{commit: '87832', patch: null, rootFile: null}, {commit: '96336', patch: null, rootFile: null}]);
assert.equal(content['commits'].length, 3);
assert.equal(content['commits'][0].id, 87832);
--- /dev/null
+'use strict';
+
+const assert = require('assert');
+
+require('../tools/js/v3-models.js');
+
+const MockData = require('./resources/mock-data.js');
+const TestServer = require('./resources/test-server.js');
+const TemporaryFile = require('./resources/temporary-file.js').TemporaryFile;
+const addSlaveForReport = require('./resources/common-operations.js').addSlaveForReport;
+const prepareServerTest = require('./resources/common-operations.js').prepareServerTest;
+
+function makeReport(rootFile, buildRequestId = 1)
+{
+ return {
+ slaveName: 'someSlave',
+ slavePassword: 'somePassword',
+ builderName: 'someBuilder',
+ buildNumber: 123,
+ buildTime: '2017-05-10T02:54:08.666',
+ buildRequest: buildRequestId,
+ rootFile: rootFile,
+ repositoryList: '["WebKit"]',
+ };
+}
+
+function addSlaveAndCreateRootFile(slaveInfo = makeReport())
+{
+ return addSlaveForReport(slaveInfo).then(() => {
+ return TemporaryFile.makeTemporaryFile('some.dat', 'some content');
+ });
+}
+
+function createTestGroupWihPatch()
+{
+ const triggerableConfiguration = {
+ 'slaveName': 'sync-slave',
+ 'slavePassword': 'password',
+ 'triggerable': 'build-webkit',
+ 'configurations': [
+ {test: MockData.someTestId(), platform: MockData.somePlatformId()},
+ ],
+ 'repositoryGroups': [
+ {name: 'webkit', repositories: [
+ {repository: MockData.webkitRepositoryId(), acceptsPatch: true},
+ {repository: MockData.sharedRepositoryId()},
+ ]}
+ ]
+ };
+
+ return MockData.addMockData(TestServer.database()).then(() => {
+ return Promise.all([TemporaryFile.makeTemporaryFile('patch.dat', 'patch file'), Manifest.fetch()]);
+ }).then((result) => {
+ const patchFile = result[0];
+ return Promise.all([UploadedFile.uploadFile(patchFile), TestServer.remoteAPI().postJSON('/api/update-triggerable/', triggerableConfiguration)]);
+ }).then((result) => {
+ const patchFile = result[0];
+ const someTest = Test.findById(MockData.someTestId());
+ const webkit = Repository.findById(MockData.webkitRepositoryId());
+ const shared = Repository.findById(MockData.sharedRepositoryId());
+ const set1 = new CustomCommitSet;
+ set1.setRevisionForRepository(webkit, '191622', patchFile);
+ set1.setRevisionForRepository(shared, '80229');
+ const set2 = new CustomCommitSet;
+ set2.setRevisionForRepository(webkit, '191622');
+ set2.setRevisionForRepository(shared, '80229');
+ return TestGroup.createWithTask('custom task', Platform.findById(MockData.somePlatformId()), someTest, 'some group', 2, [set1, set2]);
+ }).then((task) => {
+ return TestGroup.findAllByTask(task.id())[0];
+ })
+}
+
+describe('/api/upload-root/', function () {
+ prepareServerTest(this);
+ TemporaryFile.inject();
+
+ it('should reject when root file is missing', () => {
+ return TestServer.remoteAPI().postFormData('/api/upload-root/', {}).then((response) => {
+ assert.equal(response['status'], 'NoFileSpecified');
+ });
+ });
+
+ it('should reject when there are no slaves', () => {
+ return TemporaryFile.makeTemporaryFile('some.dat', 'some content').then((rootFile) => {
+ return TestServer.remoteAPI().postFormData('/api/upload-root/', makeReport(rootFile));
+ }).then((response) => {
+ assert.equal(response['status'], 'SlaveNotFound');
+ });
+ });
+
+ it('should reject when slave name is missing', () => {
+ return addSlaveAndCreateRootFile().then((rootFile) => {
+ const report = makeReport(rootFile);
+ delete report.slaveName;
+ return TestServer.remoteAPI().postFormData('/api/upload-root/', report);
+ }).then((response) => {
+ assert.equal(response['status'], 'MissingSlaveName');
+ });
+ });
+
+ it('should reject when builder name is missing', () => {
+ return addSlaveAndCreateRootFile().then((rootFile) => {
+ const report = makeReport(rootFile);
+ delete report.builderName;
+ return TestServer.remoteAPI().postFormData('/api/upload-root/', report);
+ }).then((response) => {
+ assert.equal(response['status'], 'InvalidBuilderName');
+ });
+ });
+
+ it('should reject when build number is missing', () => {
+ return addSlaveAndCreateRootFile().then((rootFile) => {
+ const report = makeReport(rootFile);
+ delete report.buildNumber;
+ return TestServer.remoteAPI().postFormData('/api/upload-root/', report);
+ }).then((response) => {
+ assert.equal(response['status'], 'InvalidBuildNumber');
+ });
+ });
+
+ it('should reject when build number is not a number', () => {
+ return addSlaveAndCreateRootFile().then((rootFile) => {
+ const report = makeReport(rootFile);
+ report.buildNumber = '1abc';
+ return TestServer.remoteAPI().postFormData('/api/upload-root/', report);
+ }).then((response) => {
+ assert.equal(response['status'], 'InvalidBuildNumber');
+ });
+ });
+
+ it('should reject when build time is missing', () => {
+ return addSlaveAndCreateRootFile().then((rootFile) => {
+ const report = makeReport(rootFile);
+ delete report.buildTime;
+ return TestServer.remoteAPI().postFormData('/api/upload-root/', report);
+ }).then((response) => {
+ assert.equal(response['status'], 'InvalidBuildTime');
+ });
+ });
+
+ it('should reject when build time is malformed', () => {
+ return addSlaveAndCreateRootFile().then((rootFile) => {
+ const report = makeReport(rootFile);
+ report.buildTime = 'Wed, 10 May 2017 03:02:30 GMT';
+ return TestServer.remoteAPI().postFormData('/api/upload-root/', report);
+ }).then((response) => {
+ assert.equal(response['status'], 'InvalidBuildTime');
+ });
+ });
+
+ it('should reject when build request ID is missing', () => {
+ return addSlaveAndCreateRootFile().then((rootFile) => {
+ const report = makeReport(rootFile);
+ delete report.buildRequest;
+ return TestServer.remoteAPI().postFormData('/api/upload-root/', report);
+ }).then((response) => {
+ assert.equal(response['status'], 'InvalidBuildRequest');
+ });
+ });
+
+ it('should reject when build request ID is not a number', () => {
+ return addSlaveAndCreateRootFile().then((rootFile) => {
+ const report = makeReport(rootFile);
+ report.buildRequest = 'abc';
+ return TestServer.remoteAPI().postFormData('/api/upload-root/', report);
+ }).then((response) => {
+ assert.equal(response['status'], 'InvalidBuildRequest');
+ });
+ });
+
+ it('should reject when build request does not exist', () => {
+ return addSlaveAndCreateRootFile().then((rootFile) => {
+ return TestServer.remoteAPI().postFormData('/api/upload-root/', makeReport(rootFile));
+ }).then((response) => {
+ assert.equal(response['status'], 'InvalidBuildRequestType');
+ });
+ });
+
+ it('should reject when repository list is missing', () => {
+ return addSlaveAndCreateRootFile().then((rootFile) => {
+ const report = makeReport(rootFile);
+ delete report.repositoryList;
+ return TestServer.remoteAPI().postFormData('/api/upload-root/', report);
+ }).then((response) => {
+ assert.equal(response['status'], 'InvalidRepositoryList');
+ });
+ });
+
+ it('should reject when repository list is not a valid JSON string', () => {
+ return addSlaveAndCreateRootFile().then((rootFile) => {
+ const report = makeReport(rootFile);
+ report.repositoryList = 'a+b';
+ return TestServer.remoteAPI().postFormData('/api/upload-root/', report);
+ }).then((response) => {
+ assert.equal(response['status'], 'InvalidRepositoryList');
+ });
+ });
+
+ it('should accept when build request exists', () => {
+ let webkit;
+ let webkitPatch;
+ let shared;
+ let testGroup;
+ let buildRequest;
+ let otherBuildRequest;
+ let uploadedRoot;
+ return createTestGroupWihPatch().then((group) => {
+ webkit = Repository.findById(MockData.webkitRepositoryId());
+ shared = Repository.findById(MockData.sharedRepositoryId());
+
+ testGroup = group;
+ buildRequest = testGroup.buildRequests()[0];
+ assert.equal(testGroup.buildRequests().length, 6);
+
+ assert(buildRequest.isBuild());
+ assert(!buildRequest.isTest());
+ assert(!buildRequest.hasFinished());
+ assert(buildRequest.isPending());
+ assert.equal(buildRequest.buildId(), null);
+
+ const commitSet = buildRequest.commitSet();
+ assert.equal(commitSet.revisionForRepository(webkit), '191622');
+ webkitPatch = commitSet.patchForRepository(webkit);
+ assert(webkitPatch instanceof UploadedFile);
+ assert.equal(webkitPatch.filename(), 'patch.dat');
+ assert.equal(commitSet.rootForRepository(webkit), null);
+ assert.equal(commitSet.revisionForRepository(shared), '80229');
+ assert.equal(commitSet.patchForRepository(shared), null);
+ assert.equal(commitSet.rootForRepository(shared), null);
+ assert.deepEqual(commitSet.allRootFiles(), []);
+
+ otherBuildRequest = testGroup.buildRequests()[1];
+ const otherCommitSet = otherBuildRequest.commitSet();
+ assert.equal(otherCommitSet.revisionForRepository(webkit), '191622');
+ assert.equal(otherCommitSet.patchForRepository(webkit), null);
+ assert.equal(otherCommitSet.rootForRepository(webkit), null);
+ assert.equal(otherCommitSet.revisionForRepository(shared), '80229');
+ assert.equal(otherCommitSet.patchForRepository(shared), null);
+ assert.equal(otherCommitSet.rootForRepository(shared), null);
+ assert.deepEqual(otherCommitSet.allRootFiles(), []);
+
+ return addSlaveAndCreateRootFile();
+ }).then((rootFile) => {
+ return TestServer.remoteAPI().postFormData('/api/upload-root/', makeReport(rootFile, buildRequest.id()));
+ }).then((response) => {
+ assert.equal(response['status'], 'OK');
+ const uploadedRootRawData = response['uploadedFile'];
+ uploadedRoot = UploadedFile.ensureSingleton(uploadedRootRawData.id, uploadedRootRawData);
+ assert.equal(uploadedRoot.filename(), 'some.dat');
+ return TestGroup.fetchForTask(buildRequest.testGroup().task().id(), true);
+ }).then((testGroups) => {
+
+ assert.equal(testGroups.length, 1);
+ const group = testGroups[0];
+ assert.equal(group, testGroup);
+ assert.equal(testGroup.buildRequests().length, 6);
+
+ const updatedBuildRequest = testGroup.buildRequests()[0];
+ assert.equal(updatedBuildRequest, buildRequest);
+
+ assert(buildRequest.isBuild());
+ assert(!buildRequest.isTest());
+ assert(buildRequest.hasFinished());
+ assert(!buildRequest.isPending());
+ assert.notEqual(buildRequest.buildId(), null);
+
+ const commitSet = buildRequest.commitSet();
+ assert.equal(commitSet.revisionForRepository(webkit), '191622');
+ assert.equal(commitSet.patchForRepository(webkit), webkitPatch);
+ const webkitRoot = commitSet.rootForRepository(webkit);
+ assert.equal(webkitRoot, uploadedRoot);
+ assert.equal(commitSet.revisionForRepository(shared), '80229');
+ assert.equal(commitSet.patchForRepository(shared), null);
+ assert.equal(commitSet.rootForRepository(shared), null);
+ assert.deepEqual(commitSet.allRootFiles(), [uploadedRoot]);
+
+ const otherCommitSet = otherBuildRequest.commitSet();
+ assert.equal(otherCommitSet.revisionForRepository(webkit), '191622');
+ assert.equal(otherCommitSet.patchForRepository(webkit), null);
+ assert.equal(otherCommitSet.rootForRepository(webkit), null);
+ assert.equal(otherCommitSet.revisionForRepository(shared), '80229');
+ assert.equal(otherCommitSet.patchForRepository(shared), null);
+ assert.equal(otherCommitSet.rootForRepository(shared), null);
+ assert.deepEqual(otherCommitSet.allRootFiles(), []);
+ });
+ });
+
+ it('should reject when the repository list is not an array', () => {
+ let buildRequest;
+ return createTestGroupWihPatch().then((group) => {
+ buildRequest = group.buildRequests()[0];
+ return addSlaveAndCreateRootFile();
+ }).then((rootFile) => {
+ const report = makeReport(rootFile, buildRequest.id());
+ report.repositoryList = '"a"';
+ return TestServer.remoteAPI().postFormData('/api/upload-root/', report);
+ }).then((response) => {
+ assert.equal(response['status'], 'InvalidRepositoryList');
+ });
+ });
+
+ it('should reject when the repository list refers to a non-existent repository', () => {
+ let buildRequest;
+ return createTestGroupWihPatch().then((group) => {
+ buildRequest = group.buildRequests()[0];
+ return addSlaveAndCreateRootFile();
+ }).then((rootFile) => {
+ const report = makeReport(rootFile, buildRequest.id());
+ report.repositoryList = '["WebKit", "BadRepositoryName"]';
+ return TestServer.remoteAPI().postFormData('/api/upload-root/', report);
+ }).then((response) => {
+ assert.equal(response['status'], 'InvalidRepository');
+ assert.equal(response['repositoryName'], 'BadRepositoryName');
+ });
+ });
+
+ it('should reject when the repository list refers to a repository not present in the commit set', () => {
+ let buildRequest;
+ return createTestGroupWihPatch().then((group) => {
+ buildRequest = group.buildRequests()[0];
+ return addSlaveAndCreateRootFile();
+ }).then((rootFile) => {
+ const report = makeReport(rootFile, buildRequest.id());
+ report.repositoryList = '["WebKit", "macOS"]';
+ return TestServer.remoteAPI().postFormData('/api/upload-root/', report);
+ }).then((response) => {
+ assert.equal(response['status'], 'InvalidRepository');
+ assert.equal(response['repositoryName'], 'macOS');
+ });
+ });
+
+ it('should update all commit set items in the repository listed', () => {
+ let webkit;
+ let webkitPatch;
+ let shared;
+ let testGroup;
+ let buildRequest;
+ let otherBuildRequest;
+ let uploadedRoot;
+ return createTestGroupWihPatch().then((group) => {
+ webkit = Repository.findById(MockData.webkitRepositoryId());
+ shared = Repository.findById(MockData.sharedRepositoryId());
+
+ testGroup = group;
+ buildRequest = testGroup.buildRequests()[0];
+ assert.equal(testGroup.buildRequests().length, 6);
+
+ assert(buildRequest.isBuild());
+ assert(!buildRequest.isTest());
+ assert(!buildRequest.hasFinished());
+ assert(buildRequest.isPending());
+ assert.equal(buildRequest.buildId(), null);
+
+ const commitSet = buildRequest.commitSet();
+ assert.equal(commitSet.revisionForRepository(webkit), '191622');
+ webkitPatch = commitSet.patchForRepository(webkit);
+ assert(webkitPatch instanceof UploadedFile);
+ assert.equal(webkitPatch.filename(), 'patch.dat');
+ assert.equal(commitSet.rootForRepository(webkit), null);
+ assert.equal(commitSet.revisionForRepository(shared), '80229');
+ assert.equal(commitSet.patchForRepository(shared), null);
+ assert.equal(commitSet.rootForRepository(shared), null);
+ assert.deepEqual(commitSet.allRootFiles(), []);
+
+ otherBuildRequest = testGroup.buildRequests()[1];
+ const otherCommitSet = otherBuildRequest.commitSet();
+ assert.equal(otherCommitSet.revisionForRepository(webkit), '191622');
+ assert.equal(otherCommitSet.patchForRepository(webkit), null);
+ assert.equal(otherCommitSet.rootForRepository(webkit), null);
+ assert.equal(otherCommitSet.revisionForRepository(shared), '80229');
+ assert.equal(otherCommitSet.patchForRepository(shared), null);
+ assert.equal(otherCommitSet.rootForRepository(shared), null);
+ assert.deepEqual(otherCommitSet.allRootFiles(), []);
+
+ return addSlaveAndCreateRootFile();
+ }).then((rootFile) => {
+ const report = makeReport(rootFile, buildRequest.id());
+ report.repositoryList = '["WebKit", "Shared"]';
+ return TestServer.remoteAPI().postFormData('/api/upload-root/', report);
+ }).then((response) => {
+ assert.equal(response['status'], 'OK');
+ const uploadedRootRawData = response['uploadedFile'];
+ uploadedRoot = UploadedFile.ensureSingleton(uploadedRootRawData.id, uploadedRootRawData);
+ assert.equal(uploadedRoot.filename(), 'some.dat');
+ return TestGroup.fetchForTask(buildRequest.testGroup().task().id(), true);
+ }).then((testGroups) => {
+
+ assert.equal(testGroups.length, 1);
+ const group = testGroups[0];
+ assert.equal(group, testGroup);
+ assert.equal(testGroup.buildRequests().length, 6);
+
+ const updatedBuildRequest = testGroup.buildRequests()[0];
+ assert.equal(updatedBuildRequest, buildRequest);
+
+ assert(buildRequest.isBuild());
+ assert(!buildRequest.isTest());
+ assert(buildRequest.hasFinished());
+ assert(!buildRequest.isPending());
+ assert.notEqual(buildRequest.buildId(), null);
+
+ const commitSet = buildRequest.commitSet();
+ assert.equal(commitSet.revisionForRepository(webkit), '191622');
+ assert.equal(commitSet.patchForRepository(webkit), webkitPatch);
+ assert.equal(commitSet.rootForRepository(webkit), uploadedRoot);
+ assert.equal(commitSet.revisionForRepository(shared), '80229');
+ assert.equal(commitSet.patchForRepository(shared), null);
+ assert.equal(commitSet.rootForRepository(shared), uploadedRoot);
+ assert.deepEqual(commitSet.allRootFiles(), [uploadedRoot]);
+
+ const otherCommitSet = otherBuildRequest.commitSet();
+ assert.equal(otherCommitSet.revisionForRepository(webkit), '191622');
+ assert.equal(otherCommitSet.patchForRepository(webkit), null);
+ assert.equal(otherCommitSet.rootForRepository(webkit), null);
+ assert.equal(otherCommitSet.revisionForRepository(shared), '80229');
+ assert.equal(otherCommitSet.patchForRepository(shared), null);
+ assert.equal(otherCommitSet.rootForRepository(shared), null);
+ assert.deepEqual(otherCommitSet.allRootFiles(), []);
+ });
+ });
+
+ it('should update all commit set items in the repository listed', () => {
+ let webkit;
+ let webkitPatch;
+ let shared;
+ let testGroup;
+ let buildRequest;
+ let otherBuildRequest;
+ let uploadedRoot;
+ return createTestGroupWihPatch().then((group) => {
+ webkit = Repository.findById(MockData.webkitRepositoryId());
+ shared = Repository.findById(MockData.sharedRepositoryId());
+
+ testGroup = group;
+ buildRequest = testGroup.buildRequests()[0];
+ assert.equal(testGroup.buildRequests().length, 6);
+ assert(buildRequest.isBuild());
+ assert(!buildRequest.isTest());
+ assert(!buildRequest.hasFinished());
+ assert(buildRequest.isPending());
+ assert.equal(buildRequest.buildId(), null);
+
+ const commitSet = buildRequest.commitSet();
+ assert.equal(commitSet.revisionForRepository(webkit), '191622');
+ webkitPatch = commitSet.patchForRepository(webkit);
+ assert(webkitPatch instanceof UploadedFile);
+ assert.equal(webkitPatch.filename(), 'patch.dat');
+ assert.equal(commitSet.rootForRepository(webkit), null);
+ assert.equal(commitSet.revisionForRepository(shared), '80229');
+ assert.equal(commitSet.patchForRepository(shared), null);
+ assert.equal(commitSet.rootForRepository(shared), null);
+ assert.deepEqual(commitSet.allRootFiles(), []);
+
+ otherBuildRequest = testGroup.buildRequests()[1];
+ const otherCommitSet = otherBuildRequest.commitSet();
+ assert.equal(otherCommitSet.revisionForRepository(webkit), '191622');
+ assert.equal(otherCommitSet.patchForRepository(webkit), null);
+ assert.equal(otherCommitSet.rootForRepository(webkit), null);
+ assert.equal(otherCommitSet.revisionForRepository(shared), '80229');
+ assert.equal(otherCommitSet.patchForRepository(shared), null);
+ assert.equal(otherCommitSet.rootForRepository(shared), null);
+ assert.deepEqual(otherCommitSet.allRootFiles(), []);
+
+ return addSlaveAndCreateRootFile();
+ }).then((rootFile) => {
+ const report = makeReport(rootFile, buildRequest.id());
+ report.repositoryList = '["WebKit", "Shared"]';
+ return TestServer.remoteAPI().postFormData('/api/upload-root/', report);
+ }).then((response) => {
+ assert.equal(response['status'], 'OK');
+ const uploadedRootRawData = response['uploadedFile'];
+ uploadedRoot = UploadedFile.ensureSingleton(uploadedRootRawData.id, uploadedRootRawData);
+ assert.equal(uploadedRoot.filename(), 'some.dat');
+ return TestGroup.fetchForTask(buildRequest.testGroup().task().id(), true);
+ }).then((testGroups) => {
+ assert.equal(testGroups.length, 1);
+ const group = testGroups[0];
+ assert.equal(group, testGroup);
+ assert.equal(testGroup.buildRequests().length, 6);
+
+ const updatedBuildRequest = testGroup.buildRequests()[0];
+ assert.equal(updatedBuildRequest, buildRequest);
+
+ assert(buildRequest.isBuild());
+ assert(!buildRequest.isTest());
+ assert(buildRequest.hasFinished());
+ assert(!buildRequest.isPending());
+ assert.notEqual(buildRequest.buildId(), null);
+
+ assert.deepEqual(buildRequest.commitSet().allRootFiles(), [uploadedRoot]);
+ assert.deepEqual(otherBuildRequest.commitSet().allRootFiles(), []);
+ });
+ });
+
+});
let insertedGroupId;
return PrivilegedAPI.sendRequest('create-test-group', {name: 'test', task: taskId, commitSets: {'macOS': ['15A284', '15A284'], 'WebKit': ['191622', '191623']}}).then((content) => {
insertedGroupId = content['testGroupId'];
- return TestGroup.fetchByTask(taskId);
+ return TestGroup.fetchForTask(taskId, true);
}).then((testGroups) => {
assert.equal(testGroups.length, 1);
const group = testGroups[0];
let insertedGroupId;
return PrivilegedAPI.sendRequest('create-test-group', params).then((content) => {
insertedGroupId = content['testGroupId'];
- return TestGroup.fetchByTask(taskId);
+ return TestGroup.fetchForTask(taskId, true);
}).then((testGroups) => {
assert.equal(testGroups.length, 1);
const group = testGroups[0];
return PrivilegedAPI.sendRequest('create-test-group', {name: 'test', task: taskId, repetitionCount: 2,
commitSets: {'WebKit': ['191622', '191623'], 'macOS': ['15A284', '15A284']}}).then((content) => {
insertedGroupId = content['testGroupId'];
- return TestGroup.fetchByTask(taskId);
+ return TestGroup.fetchForTask(taskId, true);
}).then((testGroups) => {
assert.equal(testGroups.length, 1);
const group = testGroups[0];
let insertedGroupId;
return PrivilegedAPI.sendRequest('create-test-group', params).then((content) => {
insertedGroupId = content['testGroupId'];
- return TestGroup.fetchByTask(taskId);
+ return TestGroup.fetchForTask(taskId, true);
}).then((testGroups) => {
assert.equal(testGroups.length, 1);
const group = testGroups[0];
{[webkit.id()]: {revision: '191622'}, [macos.id()]: {revision: '15A284'}, 'customRoots': [uploadedFile['id']]}];
return PrivilegedAPI.sendRequest('create-test-group', {name: 'test', task: taskId, repetitionCount: 2, revisionSets}).then((content) => {
insertedGroupId = content['testGroupId'];
- return TestGroup.fetchByTask(taskId);
+ return TestGroup.fetchForTask(taskId, true);
});
}).then((testGroups) => {
assert.equal(testGroups.length, 1);
return PrivilegedAPI.sendRequest('create-test-group', {name: 'test', task: taskId, repetitionCount: 2, revisionSets});
}).then((content) => {
insertedGroupId = content['testGroupId'];
- return TestGroup.fetchByTask(taskId);
+ return TestGroup.fetchForTask(taskId, true);
}).then((testGroups) => {
assert.equal(testGroups.length, 1);
const group = testGroups[0];
{name: 'test', taskName: 'other task', platform: MockData.somePlatformId(), test: MockData.someTestId(), revisionSets});
}).then((result) => {
insertedGroupId = result['testGroupId'];
- return Promise.all([AnalysisTask.fetchById(result['taskId']), TestGroup.fetchByTask(result['taskId'])]);
+ return Promise.all([AnalysisTask.fetchById(result['taskId']), TestGroup.fetchForTask(result['taskId'], true)]);
}).then((result) => {
const [analysisTask, testGroups] = result;
}).then((result) => {
secondResult = result;
assert.equal(firstResult['taskId'], secondResult['taskId']);
- return Promise.all([AnalysisTask.fetchById(result['taskId']), TestGroup.fetchByTask(result['taskId'])]);
+ return Promise.all([AnalysisTask.fetchById(result['taskId']), TestGroup.fetchForTask(result['taskId'], true)]);
}).then((result) => {
const [analysisTask, testGroups] = result;
macosRepositoryId() { return 9; },
webkitRepositoryId() { return 11; },
gitWebkitRepositoryId() { return 111; },
+ sharedRepositoryId() { return 14; },
addMockData: function (db, statusList)
{
if (!statusList)
db.insert('build_slaves', {id: 20, name: 'sync-slave', password_hash: crypto.createHash('sha256').update('password').digest('hex')}),
db.insert('repositories', {id: this.macosRepositoryId(), name: 'macOS'}),
db.insert('repositories', {id: this.webkitRepositoryId(), name: 'WebKit'}),
+ db.insert('repositories', {id: this.sharedRepositoryId(), name: 'Shared'}),
db.insert('triggerable_repository_groups', {id: 2001, name: 'webkit-svn', triggerable: 1000}),
db.insert('triggerable_repositories', {repository: this.macosRepositoryId(), group: 2001}),
db.insert('triggerable_repositories', {repository: this.webkitRepositoryId(), group: 2001}),
db.insert('commits', {id: 87832, repository: this.macosRepositoryId(), revision: '10.11 15A284'}),
db.insert('commits', {id: 93116, repository: this.webkitRepositoryId(), revision: '191622', time: (new Date(1445945816878)).toISOString()}),
db.insert('commits', {id: 96336, repository: this.webkitRepositoryId(), revision: '192736', time: (new Date(1448225325650)).toISOString()}),
+ db.insert('commits', {id: 111168, repository: this.sharedRepositoryId(), revision: '80229', time: '2016-03-02T23:17:54.3Z'}),
+ db.insert('commits', {id: 111169, repository: this.sharedRepositoryId(), revision: '80230', time: '2016-03-02T23:37:18.0Z'}),
db.insert('builds', {id: 901, number: '901', time: '2015-10-27T12:05:27.1Z'}),
db.insert('platforms', {id: MockData.somePlatformId(), name: 'some platform'}),
db.insert('platforms', {id: MockData.otherPlatformId(), name: 'other platform'}),