Extend create-analysis-test API to be able to create with confirming test group.
https://bugs.webkit.org/show_bug.cgi?id=184958
Reviewed by Ryosuke Niwa.
Extend create-analysis-test API to be able to create an analysis task with confirming test group.
Update create analysis task UI in chart pane to adapt this new API.
Refactored '/privileged-api/create-test-group' API to share some creating test group logic with '/privileged-api/create-analysis-task' API.
Moved the shared logic to commit-sets-helpers.php.
* public/api/analysis-tasks.php: Use 'require_once' instead of 'require'.
* public/include/commit-sets-helpers.php: Added.
(create_test_group_and_build_requests): A helper function that creates test group and build requests for a analysis
task. In long term, this should be a class to avoid passing long argument list around.
(insert_commit_sets_and_construct_configuration_list): Based on commit sets returns build and test configurations.
(insert_build_request_for_configuration): Insert build requests based on configuration.
(commit_sets_from_revision_sets): Returns commit sets from given revision set list.
* public/privileged-api/create-analysis-task.php: Added the ability to create analysis task with confirming test
groups when repetition count is specified.
* public/privileged-api/create-test-group.php: Moved shared function to commit-sets-helpers.php.
* public/v3/models/analysis-task.js:
(AnalysisTask.create): Instead of accepting run ids, it now accepts points and test group name and confirming iterations.
It will conditionally add test group information into parameter when confirming iterations is a positive number.
(AnalysisTask):
* public/v3/models/commit-set.js:
(CommitSet.revisionSetsFromCommitSets): Move 'TestGroup._revisionSetsFromCommitSets' since CommitSet class is more
appropriate place and it will be shared by both TestGroup and AnalysisTask
(CommitSet):
* public/v3/models/test-group.js:
(TestGroup.createWithTask): Adapt 'CommitSet.revisionSetsFromCommitSets'.
(TestGroup.createWithCustomConfiguration): Adapt 'CommitSet.revisionSetsFromCommitSets'.
(TestGroup.createAndRefetchTestGroups): Adapt 'CommitSet.revisionSetsFromCommitSets'.
(TestGroup._revisionSetsFromCommitSets): Deleted and moved to 'CommitSet.revisionSetsFromCommitSets'.
* public/v3/pages/chart-pane.js:
(ChartPane.prototype.didConstructShadowTree): Added the logic to disable options when checkbox for creating confirming
test group is unchecked.
(ChartPane.prototype._analyzeRange): Conditionally create confirming test group from UI.
(ChartPane.cssTemplate):
* server-tests/privileged-api-create-analysis-task-tests.js: Added unit tests. Added a unit test for 'NodePrivilegedAPI'.
* unit-tests/analysis-task-tests.js: Added unit tests.
* unit-tests/commit-set-tests.js: Added unit test for 'CommitSet.revisionSetsFromCommitSets'.
* unit-tests/resources/mock-remote-api.js: Reset csrf token when BrowserPrivilegedAPI is used.
(MockRemoteAPI.inject):
git-svn-id: http://svn.webkit.org/repository/webkit/trunk@231087 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/Websites/perf.webkit.org/ChangeLog b/Websites/perf.webkit.org/ChangeLog
index 82e2b48..b399bcb 100644
--- a/Websites/perf.webkit.org/ChangeLog
+++ b/Websites/perf.webkit.org/ChangeLog
@@ -1,3 +1,49 @@
+2018-04-26 Dewei Zhu <dewei_zhu@apple.com>
+
+ Extend create-analysis-test API to be able to create with confirming test group.
+ https://bugs.webkit.org/show_bug.cgi?id=184958
+
+ Reviewed by Ryosuke Niwa.
+
+ Extend create-analysis-test API to be able to create an analysis task with confirming test group.
+ Update create analysis task UI in chart pane to adapt this new API.
+ Refactored '/privileged-api/create-test-group' API to share some creating test group logic with '/privileged-api/create-analysis-task' API.
+ Moved the shared logic to commit-sets-helpers.php.
+
+ * public/api/analysis-tasks.php: Use 'require_once' instead of 'require'.
+ * public/include/commit-sets-helpers.php: Added.
+ (create_test_group_and_build_requests): A helper function that creates test group and build requests for a analysis
+ task. In long term, this should be a class to avoid passing long argument list around.
+ (insert_commit_sets_and_construct_configuration_list): Based on commit sets returns build and test configurations.
+ (insert_build_request_for_configuration): Insert build requests based on configuration.
+ (commit_sets_from_revision_sets): Returns commit sets from given revision set list.
+ * public/privileged-api/create-analysis-task.php: Added the ability to create analysis task with confirming test
+ groups when repetition count is specified.
+ * public/privileged-api/create-test-group.php: Moved shared function to commit-sets-helpers.php.
+ * public/v3/models/analysis-task.js:
+ (AnalysisTask.create): Instead of accepting run ids, it now accepts points and test group name and confirming iterations.
+ It will conditionally add test group information into parameter when confirming iterations is a positive number.
+ (AnalysisTask):
+ * public/v3/models/commit-set.js:
+ (CommitSet.revisionSetsFromCommitSets): Move 'TestGroup._revisionSetsFromCommitSets' since CommitSet class is more
+ appropriate place and it will be shared by both TestGroup and AnalysisTask
+ (CommitSet):
+ * public/v3/models/test-group.js:
+ (TestGroup.createWithTask): Adapt 'CommitSet.revisionSetsFromCommitSets'.
+ (TestGroup.createWithCustomConfiguration): Adapt 'CommitSet.revisionSetsFromCommitSets'.
+ (TestGroup.createAndRefetchTestGroups): Adapt 'CommitSet.revisionSetsFromCommitSets'.
+ (TestGroup._revisionSetsFromCommitSets): Deleted and moved to 'CommitSet.revisionSetsFromCommitSets'.
+ * public/v3/pages/chart-pane.js:
+ (ChartPane.prototype.didConstructShadowTree): Added the logic to disable options when checkbox for creating confirming
+ test group is unchecked.
+ (ChartPane.prototype._analyzeRange): Conditionally create confirming test group from UI.
+ (ChartPane.cssTemplate):
+ * server-tests/privileged-api-create-analysis-task-tests.js: Added unit tests. Added a unit test for 'NodePrivilegedAPI'.
+ * unit-tests/analysis-task-tests.js: Added unit tests.
+ * unit-tests/commit-set-tests.js: Added unit test for 'CommitSet.revisionSetsFromCommitSets'.
+ * unit-tests/resources/mock-remote-api.js: Reset csrf token when BrowserPrivilegedAPI is used.
+ (MockRemoteAPI.inject):
+
2018-04-23 Dewei Zhu <dewei_zhu@apple.com>
Tool scripts should not use PrivilegedAPI from 'public/v3/privileged-api.js'.
diff --git a/Websites/perf.webkit.org/public/api/analysis-tasks.php b/Websites/perf.webkit.org/public/api/analysis-tasks.php
index 352f723..160cff4 100644
--- a/Websites/perf.webkit.org/public/api/analysis-tasks.php
+++ b/Websites/perf.webkit.org/public/api/analysis-tasks.php
@@ -1,7 +1,7 @@
<?php
-require('../include/json-header.php');
-require('../include/commit-log-fetcher.php');
+require_once('../include/json-header.php');
+require_once('../include/commit-log-fetcher.php');
function main($path) {
$db = new Database;
diff --git a/Websites/perf.webkit.org/public/include/commit-sets-helpers.php b/Websites/perf.webkit.org/public/include/commit-sets-helpers.php
new file mode 100644
index 0000000..a7adc4f
--- /dev/null
+++ b/Websites/perf.webkit.org/public/include/commit-sets-helpers.php
@@ -0,0 +1,160 @@
+<?php
+
+require_once('repository-group-finder.php');
+require_once('commit-log-fetcher.php');
+
+# FIXME: Should create a helper class for below 3 helper functions to avoid passing long argument list.
+function create_test_group_and_build_requests($db, $commit_sets, $task_id, $name, $author, $triggerable_id, $platform_id, $test_id, $repetition_count) {
+
+ list ($build_configuration_list, $test_configuration_list) = insert_commit_sets_and_construct_configuration_list($db, $commit_sets);
+
+ $group_id = $db->insert_row('analysis_test_groups', 'testgroup',
+ array('task' => $task_id, 'name' => $name, 'author' => $author));
+
+ $build_count = count($build_configuration_list);
+ $order = -$build_count;
+ foreach($build_configuration_list as $build_configuration)
+ insert_build_request_for_configuration($db, $build_configuration, $order++, $triggerable_id, $platform_id, NULL, $group_id);
+
+ for ($i = 0; $i < $repetition_count; $i++) {
+ foreach($test_configuration_list as $test_configuration)
+ insert_build_request_for_configuration($db, $test_configuration, $order++, $triggerable_id, $platform_id, $test_id, $group_id);
+ }
+ return $group_id;
+}
+
+function insert_commit_sets_and_construct_configuration_list($db, $commit_sets)
+{
+ $repository_group_with_builds = array();
+ $test_configuration_list = array();
+ $build_configuration_list = array();
+
+ foreach ($commit_sets as $commit_list) {
+ $commit_set_id = $db->insert_row('commit_sets', 'commitset', array());
+ $need_to_build = FALSE;
+ foreach ($commit_list['set'] as $commit_row) {
+ $commit_row['set'] = $commit_set_id;
+ $requires_build = $commit_row['requires_build'];
+ assert(is_bool($requires_build));
+ $need_to_build = $need_to_build || $requires_build;
+ $db->insert_row('commit_set_items', 'commitset', $commit_row, 'commit');
+ }
+ $repository_group = $commit_list['repository_group'];
+ if ($need_to_build)
+ $repository_group_with_builds[$repository_group] = TRUE;
+ array_push($test_configuration_list, array('commit_set' => $commit_set_id, 'repository_group' => $repository_group));
+ }
+
+ foreach ($test_configuration_list as &$config) {
+ if (array_get($repository_group_with_builds, $config['repository_group']))
+ array_push($build_configuration_list, $config);
+ }
+ return array($build_configuration_list, $test_configuration_list);
+}
+
+function insert_build_request_for_configuration($db, $configuration, $order, $triggerable_id, $platform_id, $test_id, $group_id)
+{
+ $db->insert_row('build_requests', 'request', array(
+ 'triggerable' => $triggerable_id,
+ 'repository_group' => $configuration['repository_group'],
+ 'platform' => $platform_id,
+ 'test' => $test_id,
+ 'group' => $group_id,
+ 'order' => $order,
+ 'commit_set' => $configuration['commit_set']));
+}
+
+function commit_sets_from_revision_sets($db, $triggerable_id, $revision_set_list)
+{
+ if (count($revision_set_list) < 2)
+ exit_with_error('InvalidRevisionSets', array('revisionSets' => $revision_set_list));
+
+ $finder = new RepositoryGroupFinder($db, $triggerable_id);
+ $commit_set_list = array();
+ $repository_owner_list = array();
+ $repositories_require_build = array();
+ $commit_set_items_by_repository = array();
+ foreach ($revision_set_list as $revision_set) {
+ if (!count($revision_set))
+ exit_with_error('InvalidRevisionSets', array('revisionSets' => $revision_set_list));
+
+ $commit_set = array();
+ $repository_list = array();
+ $repository_with_patch = array();
+ foreach ($revision_set as $repository_id => $data) {
+ if ($repository_id == 'customRoots') {
+ $file_id_list = $data;
+ foreach ($file_id_list as $file_id) {
+ if (!is_numeric($file_id) || !$db->select_first_row('uploaded_files', 'file', array('id' => $file_id)))
+ exit_with_error('InvalidUploadedFile', array('file' => $file_id));
+ array_push($commit_set, array('root_file' => $file_id, 'patch_file' => NULL, 'requires_build' => FALSE, 'commit_owner' => NULL));
+ }
+ continue;
+ }
+ if (!is_numeric($repository_id))
+ exit_with_error('InvalidRepository', array('repository' => $repository_id));
+
+ if (!is_array($data))
+ exit_with_error('InvalidRepositoryData', array('repository' => $repository_id, 'data' => $data));
+
+ $revision = array_get($data, 'revision');
+ if (!$revision)
+ exit_with_error('InvalidRevision', array('repository' => $repository_id, 'data' => $data));
+ $commit_id = CommitLogFetcher::find_commit_id_by_revision($db, $repository_id, $revision);
+ if ($commit_id < 0)
+ exit_with_error('AmbiguousRevision', array('repository' => $repository_id, 'revision' => $revision));
+ if (!$commit_id)
+ exit_with_error('RevisionNotFound', array('repository' => $repository_id, 'revision' => $revision));
+
+ $owner_revision = array_get($data, 'ownerRevision');
+ $patch_file_id = array_get($data, 'patch');
+ if ($patch_file_id) {
+ if (!is_numeric($patch_file_id) || !$db->select_first_row('uploaded_files', 'file', array('id' => $patch_file_id)))
+ exit_with_error('InvalidPatchFile', array('patch' => $patch_file_id));
+ array_push($repository_with_patch, $repository_id);
+ $repositories_require_build[$repository_id] = TRUE;
+ }
+
+ $repository = NULL;
+ $owner_commit_id = NULL;
+ if ($owner_revision) {
+ $repository = $db->select_first_row('repositories', 'repository', array('id' => intval($repository_id)));
+ if (!$repository)
+ exit_with_error('RepositoryNotFound', array('repository' => $repository_id));
+ $owner_commit = $db->select_first_row('commits', 'commit', array('repository' => $repository['repository_owner'], 'revision' => $owner_revision));
+ if (!$owner_commit)
+ exit_with_error('InvalidOwnerRevision', array('repository' => $repository['repository_owner'], 'revision' => $owner_revision));
+ if (!$db->select_first_row('commit_ownerships', 'commit', array('owned' => $commit_id, 'owner' => $owner_commit['commit_id'])))
+ exit_with_error('InvalidCommitOwnership', array('commitOwner' => $owner_commit['commit_id'], 'commitOwned' => $commit_id));
+ $repositories_require_build[$repository_id] = TRUE;
+ $owner_commit_id = $owner_commit['commit_id'];
+ }
+
+ array_push($commit_set, array('commit' => $commit_id, 'patch_file' => $patch_file_id, 'requires_build' => FALSE, 'commit_owner' => $owner_commit_id));
+
+ array_ensure_item_has_array($commit_set_items_by_repository, $repository_id);
+ $commit_set_items_by_repository[$repository_id][] = &$commit_set[count($commit_set) - 1];
+
+ if ($owner_commit_id)
+ continue;
+ array_push($repository_list, $repository_id);
+ }
+ $repository_group_id = $finder->find_by_repositories($repository_list);
+ if (!$repository_group_id)
+ exit_with_error('NoMatchingRepositoryGroup', array('repositories' => $repository_list));
+
+ foreach ($repository_with_patch as $repository_id) {
+ if (!$finder->accepts_patch($repository_group_id, $repository_id))
+ exit_with_error('PatchNotAccepted', array('repository' => $repository_id, 'repositoryGroup' => $repository_group_id));
+ }
+
+ array_push($commit_set_list, array('repository_group' => $repository_group_id, 'set' => $commit_set));
+ }
+
+ foreach (array_keys($repositories_require_build) as $repository_id) {
+ foreach($commit_set_items_by_repository[$repository_id] as &$commit_set_item)
+ $commit_set_item['requires_build'] = TRUE;
+ }
+ return $commit_set_list;
+}
+?>
\ No newline at end of file
diff --git a/Websites/perf.webkit.org/public/privileged-api/create-analysis-task.php b/Websites/perf.webkit.org/public/privileged-api/create-analysis-task.php
index 408507a..940f80b 100644
--- a/Websites/perf.webkit.org/public/privileged-api/create-analysis-task.php
+++ b/Websites/perf.webkit.org/public/privileged-api/create-analysis-task.php
@@ -1,6 +1,7 @@
<?php
require_once('../include/json-header.php');
+require_once('../include/commit-sets-helpers.php');
function main() {
$db = connect();
@@ -8,6 +9,9 @@
$author = remote_user_name($data);
$name = array_get($data, 'name');
+ $repetition_count = array_get($data, 'repetitionCount');
+ $test_group_name = array_get($data, 'testGroupName');
+ $revision_set_list = array_get($data, 'revisionSets');
$segmentation_name = array_get($data, 'segmentationStrategy');
$test_range_name = array_get($data, 'testRangeStrategy');
@@ -66,6 +70,23 @@
'end_run_time' => $end_run_time,
'segmentation' => $segmentation_id,
'test_range' => $test_range_id));
+
+ if ($repetition_count) {
+ $triggerable = find_triggerable_for_task($db, $task_id);
+ if (!$triggerable || !$triggerable['id']) {
+ $db->rollback_transaction();
+ exit_with_error('TriggerableNotFoundForTask', array('task' => $task_id, 'platform' => $config['config_platform']));
+ }
+ if ($triggerable['platform'] != $config['config_platform']) {
+ $db->rollback_transaction();
+ exit_with_error('InconsistentPlatform', array('configPlatform' => $config['config_platform'], 'taskPlatform' => $triggerable['platform']));
+ }
+ $triggerable_id = $triggerable['id'];
+ $test_id = $triggerable['test'];
+ $commit_sets = commit_sets_from_revision_sets($db, $triggerable_id, $revision_set_list);
+ create_test_group_and_build_requests($db, $commit_sets, $task_id, $test_group_name, $author, $triggerable_id, $config['config_platform'], $test_id, $repetition_count);
+ }
+
$db->commit_transaction();
exit_with_success(array('taskId' => $task_id));
diff --git a/Websites/perf.webkit.org/public/privileged-api/create-test-group.php b/Websites/perf.webkit.org/public/privileged-api/create-test-group.php
index fa55039..56b4755 100644
--- a/Websites/perf.webkit.org/public/privileged-api/create-test-group.php
+++ b/Websites/perf.webkit.org/public/privileged-api/create-test-group.php
@@ -1,8 +1,7 @@
<?php
require_once('../include/json-header.php');
-require_once('../include/commit-log-fetcher.php');
-require_once('../include/repository-group-finder.php');
+require_once('../include/commit-sets-helpers.php');
function main()
{
@@ -86,167 +85,13 @@
if ($task_name)
$task_id = $db->insert_row('analysis_tasks', 'task', array('name' => $task_name, 'author' => $author));
- $configuration_list = array();
- $repository_group_with_builds = array();
- foreach ($commit_sets as $commit_list) {
- $commit_set_id = $db->insert_row('commit_sets', 'commitset', array());
- $need_to_build = FALSE;
- foreach ($commit_list['set'] as $commit_row) {
- $commit_row['set'] = $commit_set_id;
- $requires_build = $commit_row['requires_build'];
- assert(is_bool($requires_build));
- $need_to_build = $need_to_build || $requires_build;
- $db->insert_row('commit_set_items', 'commitset', $commit_row, 'commit');
- }
- $repository_group = $commit_list['repository_group'];
- if ($need_to_build)
- $repository_group_with_builds[$repository_group] = TRUE;
- array_push($configuration_list, array('commit_set' => $commit_set_id, 'repository_group' => $repository_group));
- }
-
- $build_count = 0;
- foreach ($configuration_list as &$config_item) {
- if (array_get($repository_group_with_builds, $config_item['repository_group'])) {
- $config_item['need_to_build'] = TRUE;
- $build_count++;
- }
- }
-
- $group_id = $db->insert_row('analysis_test_groups', 'testgroup',
- array('task' => $task_id, 'name' => $name, 'author' => $author));
-
- if ($build_count) {
- $order = -$build_count;
- foreach ($configuration_list as $config) {
- if (!array_get($config, 'need_to_build'))
- continue;
- assert($order < 0);
- $db->insert_row('build_requests', 'request', array(
- 'triggerable' => $triggerable_id,
- 'repository_group' => $config['repository_group'],
- 'platform' => $platform_id,
- 'test' => NULL,
- 'group' => $group_id,
- 'order' => $order,
- 'commit_set' => $config['commit_set']));
- $order++;
- }
- }
-
- $order = 0;
- for ($i = 0; $i < $repetition_count; $i++) {
- foreach ($configuration_list as $config) {
- $db->insert_row('build_requests', 'request', array(
- 'triggerable' => $triggerable_id,
- 'repository_group' => $config['repository_group'],
- 'platform' => $platform_id,
- 'test' => $test_id,
- 'group' => $group_id,
- 'order' => $order,
- 'commit_set' => $config['commit_set']));
- $order++;
- }
- }
+ $group_id = create_test_group_and_build_requests($db, $commit_sets, $task_id, $name, $author, $triggerable_id, $platform_id, $test_id, $repetition_count);
$db->commit_transaction();
exit_with_success(array('taskId' => $task_id, 'testGroupId' => $group_id));
}
-function commit_sets_from_revision_sets($db, $triggerable_id, $revision_set_list)
-{
- if (count($revision_set_list) < 2)
- exit_with_error('InvalidRevisionSets', array('revisionSets' => $revision_set_list));
-
- $finder = new RepositoryGroupFinder($db, $triggerable_id);
- $commit_set_list = array();
- $repository_owner_list = array();
- $repositories_require_build = array();
- $commit_set_items_by_repository = array();
- foreach ($revision_set_list as $revision_set) {
- if (!count($revision_set))
- exit_with_error('InvalidRevisionSets', array('revisionSets' => $revision_set_list));
-
- $commit_set = array();
- $repository_list = array();
- $repository_with_patch = array();
- foreach ($revision_set as $repository_id => $data) {
- if ($repository_id == 'customRoots') {
- $file_id_list = $data;
- foreach ($file_id_list as $file_id) {
- if (!is_numeric($file_id) || !$db->select_first_row('uploaded_files', 'file', array('id' => $file_id)))
- exit_with_error('InvalidUploadedFile', array('file' => $file_id));
- array_push($commit_set, array('root_file' => $file_id, 'patch_file' => NULL, 'requires_build' => FALSE, 'commit_owner' => NULL));
- }
- continue;
- }
- if (!is_numeric($repository_id))
- exit_with_error('InvalidRepository', array('repository' => $repository_id));
-
- if (!is_array($data))
- exit_with_error('InvalidRepositoryData', array('repository' => $repository_id, 'data' => $data));
-
- $revision = array_get($data, 'revision');
- if (!$revision)
- exit_with_error('InvalidRevision', array('repository' => $repository_id, 'data' => $data));
- $commit_id = CommitLogFetcher::find_commit_id_by_revision($db, $repository_id, $revision);
- if ($commit_id < 0)
- exit_with_error('AmbiguousRevision', array('repository' => $repository_id, 'revision' => $revision));
- if (!$commit_id)
- exit_with_error('RevisionNotFound', array('repository' => $repository_id, 'revision' => $revision));
-
- $owner_revision = array_get($data, 'ownerRevision');
- $patch_file_id = array_get($data, 'patch');
- if ($patch_file_id) {
- if (!is_numeric($patch_file_id) || !$db->select_first_row('uploaded_files', 'file', array('id' => $patch_file_id)))
- exit_with_error('InvalidPatchFile', array('patch' => $patch_file_id));
- array_push($repository_with_patch, $repository_id);
- $repositories_require_build[$repository_id] = TRUE;
- }
-
- $repository = NULL;
- $owner_commit_id = NULL;
- if ($owner_revision) {
- $repository = $db->select_first_row('repositories', 'repository', array('id' => intval($repository_id)));
- if (!$repository)
- exit_with_error('RepositoryNotFound', array('repository' => $repository_id));
- $owner_commit = $db->select_first_row('commits', 'commit', array('repository' => $repository['repository_owner'], 'revision' => $owner_revision));
- if (!$owner_commit)
- exit_with_error('InvalidOwnerRevision', array('repository' => $repository['repository_owner'], 'revision' => $owner_revision));
- if (!$db->select_first_row('commit_ownerships', 'commit', array('owned' => $commit_id, 'owner' => $owner_commit['commit_id'])))
- exit_with_error('InvalidCommitOwnership', array('commitOwner' => $owner_commit['commit_id'], 'commitOwned' => $commit_id));
- $repositories_require_build[$repository_id] = TRUE;
- $owner_commit_id = $owner_commit['commit_id'];
- }
-
- array_push($commit_set, array('commit' => $commit_id, 'patch_file' => $patch_file_id, 'requires_build' => FALSE, 'commit_owner' => $owner_commit_id));
-
- array_ensure_item_has_array($commit_set_items_by_repository, $repository_id);
- $commit_set_items_by_repository[$repository_id][] = &$commit_set[count($commit_set) - 1];
-
- if ($owner_commit_id)
- continue;
- array_push($repository_list, $repository_id);
- }
- $repository_group_id = $finder->find_by_repositories($repository_list);
- if (!$repository_group_id)
- exit_with_error('NoMatchingRepositoryGroup', array('repositories' => $repository_list));
-
- foreach ($repository_with_patch as $repository_id) {
- if (!$finder->accepts_patch($repository_group_id, $repository_id))
- exit_with_error('PatchNotAccepted', array('repository' => $repository_id, 'repositoryGroup' => $repository_group_id));
- }
-
- array_push($commit_set_list, array('repository_group' => $repository_group_id, 'set' => $commit_set));
- }
-
- foreach (array_keys($repositories_require_build) as $repository_id) {
- foreach($commit_set_items_by_repository[$repository_id] as &$commit_set_item)
- $commit_set_item['requires_build'] = TRUE;
- }
- return $commit_set_list;
-}
-
function ensure_commit_sets($db, $triggerable_id, $commit_sets_info) {
$repository_name_to_id = array();
foreach ($db->select_rows('repositories', 'repository', array('owner' => NULL)) as $row)
diff --git a/Websites/perf.webkit.org/public/v3/models/analysis-task.js b/Websites/perf.webkit.org/public/v3/models/analysis-task.js
index 0179be1..83cc3cd 100644
--- a/Websites/perf.webkit.org/public/v3/models/analysis-task.js
+++ b/Websites/perf.webkit.org/public/v3/models/analysis-task.js
@@ -303,13 +303,16 @@
return results;
}
- static create(name, startRunId, endRunId)
+ static create(name, startPoint, endPoint, testGroupName=null, repetitionCount=0)
{
- return PrivilegedAPI.sendRequest('create-analysis-task', {
- name: name,
- startRun: startRunId,
- endRun: endRunId,
- });
+ const parameters = {name, startRun: startPoint.id, endRun: endPoint.id};
+ if (testGroupName) {
+ console.assert(repetitionCount);
+ parameters['revisionSets'] = CommitSet.revisionSetsFromCommitSets([startPoint.commitSet(), endPoint.commitSet()]);
+ parameters['repetitionCount'] = repetitionCount;
+ parameters['testGroupName'] = testGroupName;
+ }
+ return PrivilegedAPI.sendRequest('create-analysis-task', parameters);
}
}
diff --git a/Websites/perf.webkit.org/public/v3/models/commit-set.js b/Websites/perf.webkit.org/public/v3/models/commit-set.js
index 8112d56..29a9825 100644
--- a/Websites/perf.webkit.org/public/v3/models/commit-set.js
+++ b/Websites/perf.webkit.org/public/v3/models/commit-set.js
@@ -242,6 +242,26 @@
return nameParts.join(' ');
}
+
+ static revisionSetsFromCommitSets(commitSets)
+ {
+ return commitSets.map((commitSet) => {
+ console.assert(commitSet instanceof CustomCommitSet || commitSet instanceof CommitSet);
+ const revisionSet = {};
+ for (let repository of commitSet.repositories()) {
+ const patchFile = commitSet.patchForRepository(repository);
+ revisionSet[repository.id()] = {
+ revision: commitSet.revisionForRepository(repository),
+ ownerRevision: commitSet.ownerRevisionForRepository(repository),
+ patch: patchFile ? patchFile.id() : null,
+ };
+ }
+ const customRoots = commitSet.customRoots();
+ if (customRoots && customRoots.length)
+ revisionSet['customRoots'] = customRoots.map((uploadedFile) => uploadedFile.id());
+ return revisionSet;
+ });
+ }
}
class MeasurementCommitSet extends CommitSet {
diff --git a/Websites/perf.webkit.org/public/v3/models/test-group.js b/Websites/perf.webkit.org/public/v3/models/test-group.js
index e821670..e09f142 100644
--- a/Websites/perf.webkit.org/public/v3/models/test-group.js
+++ b/Websites/perf.webkit.org/public/v3/models/test-group.js
@@ -188,7 +188,7 @@
static createWithTask(taskName, platform, test, groupName, repetitionCount, commitSets)
{
console.assert(commitSets.length == 2);
- const revisionSets = this._revisionSetsFromCommitSets(commitSets);
+ const revisionSets = CommitSet.revisionSetsFromCommitSets(commitSets);
const params = {taskName, name: groupName, platform: platform.id(), test: test.id(), repetitionCount, revisionSets};
return PrivilegedAPI.sendRequest('create-test-group', params).then((data) => {
return AnalysisTask.fetchById(data['taskId']);
@@ -200,7 +200,7 @@
static createWithCustomConfiguration(task, platform, test, groupName, repetitionCount, commitSets)
{
console.assert(commitSets.length == 2);
- const revisionSets = this._revisionSetsFromCommitSets(commitSets);
+ const revisionSets = CommitSet.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.fetchForTask(data['taskId'], true);
@@ -210,7 +210,7 @@
static createAndRefetchTestGroups(task, name, repetitionCount, commitSets)
{
console.assert(commitSets.length == 2);
- const revisionSets = this._revisionSetsFromCommitSets(commitSets);
+ const revisionSets = CommitSet.revisionSetsFromCommitSets(commitSets);
return PrivilegedAPI.sendRequest('create-test-group', {
task: task.id(),
name: name,
@@ -219,26 +219,6 @@
}).then((data) => this.fetchForTask(data['taskId'], true));
}
- static _revisionSetsFromCommitSets(commitSets)
- {
- return commitSets.map((commitSet) => {
- console.assert(commitSet instanceof CustomCommitSet || commitSet instanceof CommitSet);
- const revisionSet = {};
- for (let repository of commitSet.repositories()) {
- const patchFile = commitSet.patchForRepository(repository);
- revisionSet[repository.id()] = {
- revision: commitSet.revisionForRepository(repository),
- ownerRevision: commitSet.ownerRevisionForRepository(repository),
- patch: patchFile ? patchFile.id() : null,
- };
- }
- const customRoots = commitSet.customRoots();
- if (customRoots && customRoots.length)
- revisionSet['customRoots'] = customRoots.map((uploadedFile) => uploadedFile.id());
- return revisionSet;
- });
- }
-
static findAllByTask(taskId)
{
return TestGroup.all().filter((testGroup) => testGroup._taskId == taskId);
diff --git a/Websites/perf.webkit.org/public/v3/pages/chart-pane.js b/Websites/perf.webkit.org/public/v3/pages/chart-pane.js
index f32bdec..5fc172f 100644
--- a/Websites/perf.webkit.org/public/v3/pages/chart-pane.js
+++ b/Websites/perf.webkit.org/public/v3/pages/chart-pane.js
@@ -116,7 +116,10 @@
{
this.part('close').listenToAction('activate', () => {
this._chartsPage.closePane(this);
- })
+ });
+ const createWithTestGroupCheckbox = this.content('create-with-test-group');
+ const repetitionCount = this.content('confirm-repetition');
+ createWithTestGroupCheckbox.onchange = () => repetitionCount.disabled = !createWithTestGroupCheckbox.checked;
}
serializeState()
@@ -226,19 +229,23 @@
super._indicatorDidChange(indicatorID, isLocked);
}
- _analyzeRange(startPoint, endPoint)
+ async _analyzeRange(startPoint, endPoint)
{
const router = this._chartsPage.router();
const newWindow = window.open(router.url('analysis/task/create', {inProgress: true}), '_blank');
- const analyzePopover = this.content().querySelector('.chart-pane-analyze-popover');
- const name = analyzePopover.querySelector('input').value;
- AnalysisTask.create(name, startPoint.id, endPoint.id).then((data) => {
+ const name = this.content('task-name').value;
+ const createWithTestGroup = this.content('create-with-test-group').checked;
+ const repetitionCount = this.content('confirm-repetition').value;
+
+ try {
+ const data = await (createWithTestGroup ?
+ AnalysisTask.create(name, startPoint, endPoint, 'Confirm', repetitionCount) : AnalysisTask.create(name, startPoint, endPoint));
newWindow.location.href = router.url('analysis/task/' + data['taskId']);
this.fetchAnalysisTasks(true);
- }, (error) => {
+ } catch(error) {
newWindow.location.href = router.url('analysis/task/create', {error: error});
- });
+ }
}
_markAsOutlier(markAsOutlier, points)
@@ -558,8 +565,25 @@
<ul class="chart-pane-action-buttons buttoned-toolbar"></ul>
<ul class="chart-pane-alternative-platforms popover" style="display:none"></ul>
<form class="chart-pane-analyze-popover popover" style="display:none">
- <input type="text" required>
+ <input type="text" id="task-name" required>
<button>Create</button>
+ <li>
+ <label><input type="checkbox" id="create-with-test-group" checked></label>
+ <label>Confirm with</label>
+ <select id="confirm-repetition">
+ <option>1</option>
+ <option>2</option>
+ <option>3</option>
+ <option selected>4</option>
+ <option>5</option>
+ <option>6</option>
+ <option>7</option>
+ <option>8</option>
+ <option>9</option>
+ <option>10</option>
+ </select>
+ <label>iterations</label>
+ </li>
</form>
<ul class="chart-pane-filtering-options popover" style="display:none">
<li><label><input type="checkbox" class="enable-sampling">Sampling</label></li>
@@ -619,7 +643,7 @@
padding: 0 0;
}
- .chart-pane-actions ul {
+ .chart-pane-actions ul, form {
display: block;
padding: 0;
margin: 0 0.5rem;
diff --git a/Websites/perf.webkit.org/server-tests/privileged-api-create-analysis-task-tests.js b/Websites/perf.webkit.org/server-tests/privileged-api-create-analysis-task-tests.js
index eb60d7b..c7a6d17 100644
--- a/Websites/perf.webkit.org/server-tests/privileged-api-create-analysis-task-tests.js
+++ b/Websites/perf.webkit.org/server-tests/privileged-api-create-analysis-task-tests.js
@@ -105,7 +105,7 @@
},
}}];
-describe('/privileged-api/create-analysis-task', function () {
+describe('/privileged-api/create-analysis-task with browser privileged api', function () {
prepareServerTest(this);
it('should return "MissingName" on an empty request', () => {
@@ -334,4 +334,283 @@
});
});
+ it('should failed with "TriggerableNotFoundForTask" when there is no matching triggerable', async () => {
+ const db = TestServer.database();
+ await addBuilderForReport(reportWithRevision[0]);
+ await TestServer.remoteAPI().postJSON('/api/report/', reportWithRevision);
+ await TestServer.remoteAPI().postJSON('/api/report/', anotherReportWithRevision);
+ await Manifest.fetch();
+
+ const test1 = Test.findByPath(['Suite', 'test1']);
+ const somePlatform = Platform.findByName('some platform');
+ const configRow = await db.selectFirstRow('test_configurations', {metric: test1.metrics()[0].id(), platform: somePlatform.id()});
+ const testRuns = await db.selectRows('test_runs', {config: configRow['id']});
+ assert.equal(testRuns.length, 2);
+
+ const webkitRepositoryRow = await db.selectFirstRow('repositories', {name: 'WebKit'});
+ const webkitId = webkitRepositoryRow.id;
+
+ const oneRevisionSet = {[webkitId]: {revision: '191622'}};
+ const anotherRevisionSet = {[webkitId]: {revision: '191623'}};
+
+ let raiseException = false;
+
+ try {
+ await PrivilegedAPI.sendRequest('create-analysis-task', {name: 'confirm', repetitionCount: 1,
+ revisionSets: [oneRevisionSet, anotherRevisionSet],
+ startRun: testRuns[0]['id'], endRun: testRuns[1]['id']});
+ } catch (error) {
+ assert.equal(error, 'TriggerableNotFoundForTask');
+ raiseException = true;
+ }
+ assert.ok(raiseException);
+ });
+
+ it('should create an analysis task with no test group when repetition count is 0', async () => {
+ const db = TestServer.database();
+ await addBuilderForReport(reportWithRevision[0]);
+ await TestServer.remoteAPI().postJSON('/api/report/', reportWithRevision);
+ await TestServer.remoteAPI().postJSON('/api/report/', anotherReportWithRevision);
+ await Manifest.fetch();
+
+ const test1 = Test.findByPath(['Suite', 'test1']);
+ const platform = Platform.findByName('some platform');
+ const configRow = await db.selectFirstRow('test_configurations', {metric: test1.metrics()[0].id(), platform: platform.id()});
+ const testRuns = await db.selectRows('test_runs', {config: configRow['id']});
+ assert.equal(testRuns.length, 2);
+
+ const webkitRepositoryRow = await db.selectFirstRow('repositories', {name: 'WebKit'});
+ const webkitId = webkitRepositoryRow.id;
+
+ const oneRevisionSet = {[webkitId]: {revision: '191622'}};
+ const anotherRevisionSet = {[webkitId]: {revision: '191623'}};
+
+ const content = await PrivilegedAPI.sendRequest('create-analysis-task', {name: 'confirm', repetitionCount: 0,
+ revisionSets: [oneRevisionSet, anotherRevisionSet],
+ startRun: testRuns[0]['id'], endRun: testRuns[1]['id']});
+
+ TestServer.cleanDataDirectory();
+ await Manifest.fetch();
+
+ const task = await AnalysisTask.fetchById(content['taskId']);
+ assert.equal(task.name(), 'confirm');
+ assert(!task.hasResults());
+ assert(!task.hasPendingRequests());
+ assert.deepEqual(task.bugs(), []);
+ assert.deepEqual(task.causes(), []);
+ assert.deepEqual(task.fixes(), []);
+ assert.equal(task.changeType(), null);
+ assert.equal(task.platform().label(), 'some platform');
+ assert.equal(task.metric().test().label(), 'test1');
+
+ const testGroups = await TestGroup.fetchForTask(task.id());
+ assert.equal(testGroups.length, 0);
+ });
+
+ it('should create an analysis task with test group when commit set list and a positive repetition count is specified', async () => {
+ const webkitId = 1;
+ const platformId = 1;
+ const test1Id = 2;
+ const triggerableId = 1234;
+
+ const db = TestServer.database();
+ await db.insert('tests', {id: 1, name: 'Suite'});
+ await db.insert('tests', {id: test1Id, name: 'test1', parent: 1});
+ await db.insert('repositories', {id: webkitId, name: 'WebKit'});
+ await db.insert('platforms', {id: platformId, name: 'some platform'});
+ await db.insert('build_triggerables', {id: 1234, name: 'test-triggerable'});
+ await db.insert('triggerable_repository_groups', {id: 2345, name: 'webkit-only', triggerable: triggerableId});
+ await db.insert('triggerable_repositories', {repository: webkitId, group: 2345});
+ await db.insert('triggerable_configurations', {test: test1Id, platform: platformId, triggerable: triggerableId});
+ await addBuilderForReport(reportWithRevision[0]);
+
+ await TestServer.remoteAPI().postJSON('/api/report/', reportWithRevision);
+ await TestServer.remoteAPI().postJSON('/api/report/', anotherReportWithRevision);
+ await Manifest.fetch();
+
+ let test1 = Test.findById(test1Id);
+ let somePlatform = Platform.findById(platformId);
+ const configRow = await db.selectFirstRow('test_configurations', {metric: test1.metrics()[0].id(), platform: somePlatform.id()});
+ const testRuns = await db.selectRows('test_runs', {config: configRow['id']});
+ assert.equal(testRuns.length, 2);
+
+ const oneRevisionSet = {[webkitId]: {revision: '191622'}};
+ const anotherRevisionSet = {[webkitId]: {revision: '191623'}};
+
+ const content = await PrivilegedAPI.sendRequest('create-analysis-task', {name: 'confirm', repetitionCount: 1,
+ testGroupName: 'Confirm', revisionSets: [oneRevisionSet, anotherRevisionSet],
+ startRun: testRuns[0]['id'], endRun: testRuns[1]['id']});
+
+ const task = await AnalysisTask.fetchById(content['taskId']);
+ assert.equal(task.name(), 'confirm');
+ assert(!task.hasResults());
+ assert(task.hasPendingRequests());
+ assert.deepEqual(task.bugs(), []);
+ assert.deepEqual(task.causes(), []);
+ assert.deepEqual(task.fixes(), []);
+ assert.equal(task.changeType(), null);
+ assert.equal(task.platform().label(), 'some platform');
+ assert.equal(task.metric().test().label(), 'test1');
+
+ const testGroups = await TestGroup.fetchForTask(task.id());
+ assert.equal(testGroups.length, 1);
+ const testGroup = testGroups[0];
+ assert.equal(testGroup.name(), 'Confirm');
+ const buildRequests = testGroup.buildRequests();
+ assert.equal(buildRequests.length, 2);
+
+ assert.equal(buildRequests[0].triggerable().id(), triggerableId);
+ assert.equal(buildRequests[0].triggerable().id(), triggerableId);
+
+ assert.equal(buildRequests[0].testGroup(), testGroup);
+ assert.equal(buildRequests[1].testGroup(), testGroup);
+
+ assert.equal(buildRequests[0].platform(), task.platform());
+ assert.equal(buildRequests[1].platform(), task.platform());
+
+ assert.equal(buildRequests[0].analysisTaskId(), task.id());
+ assert.equal(buildRequests[1].analysisTaskId(), task.id());
+
+ assert.equal(buildRequests[0].test(), test1);
+ assert.equal(buildRequests[1].test(), test1);
+
+ assert.ok(!buildRequests[0].isBuild());
+ assert.ok(!buildRequests[1].isBuild());
+ assert.ok(buildRequests[0].isTest());
+ assert.ok(buildRequests[1].isTest());
+
+ const firstCommitSet = buildRequests[0].commitSet();
+ const secondCommitSet = buildRequests[1].commitSet();
+ const webkitRepository = Repository.findById(webkitId);
+ assert.equal(firstCommitSet.commitForRepository(webkitRepository).revision(), '191622');
+ assert.equal(secondCommitSet.commitForRepository(webkitRepository).revision(), '191623');
+ });
+});
+
+describe('/privileged-api/create-analysis-task with node privileged api', function () {
+ prepareServerTest(this, 'node');
+ beforeEach(() => {
+ PrivilegedAPI.configure('test', 'password');
+ });
+
+ it('should return "SlaveNotFound" when incorrect slave user and password combination is provided and no analysis task, test group or build request should be created', async () => {
+ PrivilegedAPI.configure('test', 'wrongpassword');
+ const db = TestServer.database();
+ await addBuilderForReport(reportWithRevision[0]);
+ await TestServer.remoteAPI().postJSON('/api/report/', reportWithRevision);
+ await TestServer.remoteAPI().postJSON('/api/report/', anotherReportWithRevision);
+ await Manifest.fetch();
+
+ const test1 = Test.findByPath(['Suite', 'test1']);
+ const somePlatform = Platform.findByName('some platform');
+ const configRow = await db.selectFirstRow('test_configurations', {metric: test1.metrics()[0].id(), platform: somePlatform.id()});
+ const testRuns = await db.selectRows('test_runs', {config: configRow['id']});
+ assert.equal(testRuns.length, 2);
+
+ const webkitRepositoryRow = await db.selectFirstRow('repositories', {name: 'WebKit'});
+ const webkitId = webkitRepositoryRow.id;
+
+ const oneRevisionSet = {[webkitId]: {revision: '191622'}};
+ const anotherRevisionSet = {[webkitId]: {revision: '191623'}};
+
+ let raiseException = false;
+
+ try {
+ await PrivilegedAPI.sendRequest('create-analysis-task', {name: 'confirm', repetitionCount: 1,
+ revisionSets: [oneRevisionSet, anotherRevisionSet],
+ startRun: testRuns[0]['id'], endRun: testRuns[1]['id']});
+ } catch (error) {
+ assert.equal(error, 'SlaveNotFound');
+ raiseException = true;
+ }
+ assert.ok(raiseException);
+
+ const allAnalysisTasks = await db.selectRows('analysis_tasks');
+ assert.ok(!allAnalysisTasks.length);
+
+ const allTestGroups = await db.selectRows('analysis_test_groups');
+ assert.ok(!allTestGroups.length);
+
+ const allBuildRequests = await db.selectRows('build_requests');
+ assert.ok(!allBuildRequests.length);
+ });
+
+ it('should create an analysis task with test group when commit set list and a positive repetition count is specified', async () => {
+ const webkitId = 1;
+ const platformId = 1;
+ const test1Id = 2;
+ const triggerableId = 1234;
+
+ const db = TestServer.database();
+ await db.insert('tests', {id: 1, name: 'Suite'});
+ await db.insert('tests', {id: test1Id, name: 'test1', parent: 1});
+ await db.insert('repositories', {id: webkitId, name: 'WebKit'});
+ await db.insert('platforms', {id: platformId, name: 'some platform'});
+ await db.insert('build_triggerables', {id: 1234, name: 'test-triggerable'});
+ await db.insert('triggerable_repository_groups', {id: 2345, name: 'webkit-only', triggerable: triggerableId});
+ await db.insert('triggerable_repositories', {repository: webkitId, group: 2345});
+ await db.insert('triggerable_configurations', {test: test1Id, platform: platformId, triggerable: triggerableId});
+ await addBuilderForReport(reportWithRevision[0]);
+
+ await TestServer.remoteAPI().postJSON('/api/report/', reportWithRevision);
+ await TestServer.remoteAPI().postJSON('/api/report/', anotherReportWithRevision);
+ await Manifest.fetch();
+
+ let test1 = Test.findById(test1Id);
+ let somePlatform = Platform.findById(platformId);
+ const configRow = await db.selectFirstRow('test_configurations', {metric: test1.metrics()[0].id(), platform: somePlatform.id()});
+ const testRuns = await db.selectRows('test_runs', {config: configRow['id']});
+ assert.equal(testRuns.length, 2);
+
+ const oneRevisionSet = {[webkitId]: {revision: '191622'}};
+ const anotherRevisionSet = {[webkitId]: {revision: '191623'}};
+
+ const content = await PrivilegedAPI.sendRequest('create-analysis-task', {name: 'confirm', repetitionCount: 1,
+ testGroupName: 'Confirm', revisionSets: [oneRevisionSet, anotherRevisionSet],
+ startRun: testRuns[0]['id'], endRun: testRuns[1]['id']});
+
+ const task = await AnalysisTask.fetchById(content['taskId']);
+ assert.equal(task.name(), 'confirm');
+ assert(!task.hasResults());
+ assert(task.hasPendingRequests());
+ assert.deepEqual(task.bugs(), []);
+ assert.deepEqual(task.causes(), []);
+ assert.deepEqual(task.fixes(), []);
+ assert.equal(task.changeType(), null);
+ assert.equal(task.platform().label(), 'some platform');
+ assert.equal(task.metric().test().label(), 'test1');
+
+ const testGroups = await TestGroup.fetchForTask(task.id());
+ assert.equal(testGroups.length, 1);
+ const testGroup = testGroups[0];
+ assert.equal(testGroup.name(), 'Confirm');
+ const buildRequests = testGroup.buildRequests();
+ assert.equal(buildRequests.length, 2);
+
+ assert.equal(buildRequests[0].triggerable().id(), triggerableId);
+ assert.equal(buildRequests[0].triggerable().id(), triggerableId);
+
+ assert.equal(buildRequests[0].testGroup(), testGroup);
+ assert.equal(buildRequests[1].testGroup(), testGroup);
+
+ assert.equal(buildRequests[0].platform(), task.platform());
+ assert.equal(buildRequests[1].platform(), task.platform());
+
+ assert.equal(buildRequests[0].analysisTaskId(), task.id());
+ assert.equal(buildRequests[1].analysisTaskId(), task.id());
+
+ assert.equal(buildRequests[0].test(), test1);
+ assert.equal(buildRequests[1].test(), test1);
+
+ assert.ok(!buildRequests[0].isBuild());
+ assert.ok(!buildRequests[1].isBuild());
+ assert.ok(buildRequests[0].isTest());
+ assert.ok(buildRequests[1].isTest());
+
+ const firstCommitSet = buildRequests[0].commitSet();
+ const secondCommitSet = buildRequests[1].commitSet();
+ const webkitRepository = Repository.findById(webkitId);
+ assert.equal(firstCommitSet.commitForRepository(webkitRepository).revision(), '191622');
+ assert.equal(secondCommitSet.commitForRepository(webkitRepository).revision(), '191623');
+ });
});
diff --git a/Websites/perf.webkit.org/unit-tests/analysis-task-tests.js b/Websites/perf.webkit.org/unit-tests/analysis-task-tests.js
index d696f68..5d499ab 100644
--- a/Websites/perf.webkit.org/unit-tests/analysis-task-tests.js
+++ b/Websites/perf.webkit.org/unit-tests/analysis-task-tests.js
@@ -121,9 +121,15 @@
describe('AnalysisTask', () => {
MockModels.inject();
- let requests = MockRemoteAPI.inject();
+ function makeMockPoints(id, commitSet) {
+ return {
+ id,
+ commitSet: () => commitSet
+ }
+ }
describe('fetchAll', () => {
+ const requests = MockRemoteAPI.inject();
it('should request all analysis tasks', () => {
let callCount = 0;
AnalysisTask.fetchAll().then(() => { callCount++; });
@@ -224,4 +230,89 @@
});
});
});
+
+
+ function mockStartAndEndPoints() {
+ const startPoint = makeMockPoints(1, new MeasurementCommitSet(1, [
+ [1, MockModels.ios.id(), 'ios-revision-1', null, 0],
+ [3, MockModels.webkit.id(), 'webkit-revision-1', null, 0]
+ ]));
+ const endPoint = makeMockPoints(2, new MeasurementCommitSet(2, [
+ [2, MockModels.ios.id(), 'ios-revision-2', null, 0],
+ [4, MockModels.webkit.id(), 'webkit-revision-2', null, 0]
+ ]));
+ return [startPoint, endPoint];
+ }
+
+ describe('create with browser privilege api', () => {
+ const requests = MockRemoteAPI.inject();
+
+ it('should create analysis task with confirming repetition count zero as default with browser privilege api', async () => {
+ const [startPoint, endPoint] = mockStartAndEndPoints();
+ AnalysisTask.create('confirm', startPoint, endPoint);
+ assert.equal(requests.length, 1);
+ assert.equal(requests[0].url, '/privileged-api/generate-csrf-token');
+ requests[0].resolve({
+ token: 'abc',
+ expiration: Date.now() + 3600 * 1000,
+ });
+
+ await MockRemoteAPI.waitForRequest();
+ assert.equal(requests[1].url, '/privileged-api/create-analysis-task');
+ assert.equal(requests.length, 2);
+ assert.deepEqual(requests[1].data, {name: 'confirm', startRun: 1, endRun: 2, token: 'abc'});
+ });
+
+ it('should create analysis task with confirming repetition count specified', async () => {
+ const [startPoint, endPoint] = mockStartAndEndPoints();
+ AnalysisTask.create('confirm', startPoint, endPoint, 'Confirm', 4);
+ assert.equal(requests.length, 1);
+ assert.equal(requests[0].url, '/privileged-api/generate-csrf-token');
+ requests[0].resolve({
+ token: 'abc',
+ expiration: Date.now() + 3600 * 1000,
+ });
+
+ await MockRemoteAPI.waitForRequest();
+ assert.equal(requests[1].url, '/privileged-api/create-analysis-task');
+ assert.equal(requests.length, 2);
+ assert.deepEqual(requests[1].data, {name: 'confirm', repetitionCount: 4,
+ startRun: 1, endRun: 2, testGroupName: 'Confirm', token: 'abc', revisionSets: [
+ {'11': {revision: 'webkit-revision-1', ownerRevision: null, patch: null},
+ '22': {revision: 'ios-revision-1', ownerRevision: null, patch: null}},
+ {'11': {revision: 'webkit-revision-2', ownerRevision: null, patch: null},
+ '22': { revision: 'ios-revision-2', ownerRevision: null, patch: null}}]}
+ );
+ });
+ });
+
+ describe('create with node privilege api', () => {
+ const requests = MockRemoteAPI.inject(null, 'node');
+ beforeEach(() => {
+ PrivilegedAPI.configure('worker', 'password');
+ });
+
+ it('should create analysis task with confirming repetition count zero as default with browser privilege api', () => {
+ const [startPoint, endPoint] = mockStartAndEndPoints();
+ AnalysisTask.create('confirm', startPoint, endPoint);
+ assert.equal(requests[0].url, '/privileged-api/create-analysis-task');
+ assert.equal(requests.length, 1);
+ assert.deepEqual(requests[0].data, {name: 'confirm', startRun: 1, endRun: 2, slaveName: 'worker', slavePassword: 'password'});
+ });
+
+ it('should create analysis task with confirming repetition count specified', () => {
+ const [startPoint, endPoint] = mockStartAndEndPoints();
+ AnalysisTask.create('confirm', startPoint, endPoint, 'Confirm', 4);
+ assert.equal(requests[0].url, '/privileged-api/create-analysis-task');
+ assert.equal(requests.length, 1);
+ assert.deepEqual(requests[0].data, {name: 'confirm', repetitionCount: 4,
+ startRun: 1, endRun: 2, slaveName: 'worker', slavePassword: 'password',
+ testGroupName: 'Confirm', revisionSets: [
+ {'11': {revision: 'webkit-revision-1', ownerRevision: null, patch: null},
+ '22': {revision: 'ios-revision-1', ownerRevision: null, patch: null}},
+ {'11': {revision: 'webkit-revision-2', ownerRevision: null, patch: null},
+ '22': { revision: 'ios-revision-2', ownerRevision: null, patch: null}}]}
+ );
+ });
+ });
});
diff --git a/Websites/perf.webkit.org/unit-tests/commit-set-tests.js b/Websites/perf.webkit.org/unit-tests/commit-set-tests.js
index 646deed..a8f345f 100644
--- a/Websites/perf.webkit.org/unit-tests/commit-set-tests.js
+++ b/Websites/perf.webkit.org/unit-tests/commit-set-tests.js
@@ -387,6 +387,15 @@
assert.equal(CommitSet.diff(oneCommitSet(), commitSetWithAnotherCommitPatchAndRoot()), 'WebKit: webkit-commit-0 with none - webkit-commit-1 with patch.dat Roots: none - root.dat, root.dat (2)');
});
});
+
+ describe('revisionSetsFromCommitSets', () => {
+ it('should create revision sets from commit sets', () => {
+ assert.deepEqual(CommitSet.revisionSetsFromCommitSets([oneCommitSet(), commitSetWithRoot(), commitSetWithTwoRoots()]),
+ [{'11': { revision: 'webkit-commit-0', ownerRevision: null, patch: null}},
+ {'11': { revision: 'webkit-commit-0', ownerRevision: null, patch: null}, customRoots: [456]},
+ {'11': { revision: 'webkit-commit-0', ownerRevision: null, patch: null}, customRoots: [456, 458]}]);
+ });
+ });
});
describe('IntermediateCommitSet', () => {
diff --git a/Websites/perf.webkit.org/unit-tests/resources/mock-remote-api.js b/Websites/perf.webkit.org/unit-tests/resources/mock-remote-api.js
index dc12782..6bc10fb 100644
--- a/Websites/perf.webkit.org/unit-tests/resources/mock-remote-api.js
+++ b/Websites/perf.webkit.org/unit-tests/resources/mock-remote-api.js
@@ -65,7 +65,8 @@
console.assert(privilegedAPIType === 'browser' || privilegedAPIType === 'node');
let originalRemoteAPI = global.RemoteAPI;
let originalPrivilegedAPI = global.PrivilegedAPI;
- const PrivilegedAPI = privilegedAPIType === 'node' ? NodePrivilegedAPI: BrowserPrivilegedAPI;
+ const useNodePrivilegedAPI = privilegedAPIType === 'node';
+ const PrivilegedAPI = useNodePrivilegedAPI ? NodePrivilegedAPI: BrowserPrivilegedAPI;
beforeEach(() => {
MockRemoteAPI.reset(urlPrefix);
@@ -73,6 +74,8 @@
global.RemoteAPI = MockRemoteAPI;
originalPrivilegedAPI = global.PrivilegedAPI;
global.PrivilegedAPI = PrivilegedAPI;
+ if (!useNodePrivilegedAPI)
+ PrivilegedAPI._token = null;
});
afterEach(() => {