| // Copyright (C) 2022 The Android Open Source Project | |
| // | |
| // Licensed under the Apache License, Version 2.0 (the "License"); | |
| // you may not use this file except in compliance with the License. | |
| // You may obtain a copy of the License at | |
| // | |
| // http://www.apache.org/licenses/LICENSE-2.0 | |
| // | |
| // Unless required by applicable law or agreed to in writing, software | |
| // distributed under the License is distributed on an "AS IS" BASIS, | |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
| // See the License for the specific language governing permissions and | |
| // limitations under the License. | |
| package com.google.gerrit.acceptance.api.project; | |
| import static com.google.common.truth.Truth.assertThat; | |
| import static com.google.gerrit.acceptance.GitUtil.fetch; | |
| import com.google.common.collect.ImmutableList; | |
| import com.google.common.collect.ImmutableMap; | |
| import com.google.gerrit.acceptance.AbstractDaemonTest; | |
| import com.google.gerrit.acceptance.PushOneCommit; | |
| import com.google.gerrit.acceptance.testsuite.project.ProjectOperations; | |
| import com.google.gerrit.common.Nullable; | |
| import com.google.gerrit.common.RawInputUtil; | |
| import com.google.gerrit.entities.LabelFunction; | |
| import com.google.gerrit.entities.RefNames; | |
| import com.google.gerrit.entities.SubmitRequirement; | |
| import com.google.gerrit.entities.SubmitRequirementExpression; | |
| import com.google.gerrit.extensions.api.changes.PublishChangeEditInput; | |
| import com.google.gerrit.extensions.client.ChangeStatus; | |
| import com.google.gerrit.extensions.common.ChangeInfo; | |
| import com.google.gerrit.extensions.common.ChangeInput; | |
| import com.google.gerrit.git.ObjectIds; | |
| import com.google.gerrit.server.group.SystemGroupBackend; | |
| import com.google.gerrit.server.project.GroupList; | |
| import com.google.gerrit.server.project.LabelConfigValidator; | |
| import com.google.gerrit.server.project.ProjectConfig; | |
| import com.google.inject.Inject; | |
| import org.eclipse.jgit.junit.TestRepository; | |
| import org.eclipse.jgit.lib.AnyObjectId; | |
| import org.eclipse.jgit.lib.Repository; | |
| import org.eclipse.jgit.revwalk.RevCommit; | |
| import org.junit.Test; | |
| public class ProjectConfigIT extends AbstractDaemonTest { | |
| private static final String INVALID_PRROJECT_CONFIG = | |
| "[label \"Foo\"]\n" | |
| // copyAllScoresOnTrivialRebase is deprecated and no longer allowed to be set | |
| + " copyAllScoresOnTrivialRebase = true"; | |
| @Inject private ProjectOperations projectOperations; | |
| @Test | |
| public void noLabelValidationForNonRefsMetaConfigChange() throws Exception { | |
| PushOneCommit.Result r = | |
| createChange( | |
| testRepo, | |
| "refs/heads/master", | |
| "Test Change", | |
| ProjectConfig.PROJECT_CONFIG, | |
| INVALID_PRROJECT_CONFIG, | |
| /* topic= */ null); | |
| r.assertOkStatus(); | |
| approve(r.getChangeId()); | |
| gApi.changes().id(r.getChangeId()).current().submit(); | |
| assertThat(gApi.changes().id(r.getChangeId()).get().status).isEqualTo(ChangeStatus.MERGED); | |
| } | |
| @Test | |
| public void noLabelValidationForNoneProjectConfigChange() throws Exception { | |
| fetchRefsMetaConfig(); | |
| PushOneCommit.Result r = | |
| createChange( | |
| testRepo, | |
| RefNames.REFS_CONFIG, | |
| "Test Change", | |
| "foo.config", | |
| INVALID_PRROJECT_CONFIG, | |
| /* topic= */ null); | |
| r.assertOkStatus(); | |
| approve(r.getChangeId()); | |
| gApi.changes().id(r.getChangeId()).current().submit(); | |
| assertThat(gApi.changes().id(r.getChangeId()).get().status).isEqualTo(ChangeStatus.MERGED); | |
| } | |
| @Test | |
| public void validateNoIssues_push() throws Exception { | |
| fetchRefsMetaConfig(); | |
| PushOneCommit push = | |
| pushFactory.create( | |
| admin.newIdent(), | |
| testRepo, | |
| "Test Change", | |
| ProjectConfig.PROJECT_CONFIG, | |
| "[label \"Foo\"]\n description = Foo Label"); | |
| PushOneCommit.Result r = push.to("refs/for/" + RefNames.REFS_CONFIG); | |
| r.assertOkStatus(); | |
| approve(r.getChangeId()); | |
| gApi.changes().id(r.getChangeId()).current().submit(); | |
| assertThat(gApi.changes().id(r.getChangeId()).get().status).isEqualTo(ChangeStatus.MERGED); | |
| } | |
| @Test | |
| public void validateNoIssues_createChangeApi() throws Exception { | |
| ChangeInput changeInput = new ChangeInput(); | |
| changeInput.project = project.get(); | |
| changeInput.branch = RefNames.REFS_CONFIG; | |
| changeInput.subject = "A change"; | |
| changeInput.status = ChangeStatus.NEW; | |
| ChangeInfo changeInfo = gApi.changes().create(changeInput).get(); | |
| gApi.changes().id(changeInfo.id).edit().create(); | |
| gApi.changes() | |
| .id(changeInfo.id) | |
| .edit() | |
| .modifyFile( | |
| ProjectConfig.PROJECT_CONFIG, | |
| RawInputUtil.create("[label \"Foo\"]\n description = Foo Label")); | |
| PublishChangeEditInput publishInput = new PublishChangeEditInput(); | |
| gApi.changes().id(changeInfo.id).edit().publish(publishInput); | |
| approve(changeInfo.id); | |
| gApi.changes().id(changeInfo.id).current().submit(); | |
| assertThat(gApi.changes().id(changeInfo.id).get().status).isEqualTo(ChangeStatus.MERGED); | |
| } | |
| @Test | |
| public void rejectSettingCopyAnyScore() throws Exception { | |
| testRejectSettingLabelFlag( | |
| LabelConfigValidator.KEY_COPY_ANY_SCORE, /* value= */ true, "is:ANY"); | |
| testRejectSettingLabelFlag( | |
| LabelConfigValidator.KEY_COPY_ANY_SCORE, /* value= */ false, "is:ANY"); | |
| } | |
| @Test | |
| public void rejectCreatingLabelWithInvalidFunction() throws Exception { | |
| fetchRefsMetaConfig(); | |
| PushOneCommit push = | |
| pushFactory.create( | |
| admin.newIdent(), | |
| testRepo, | |
| "Test Change", | |
| ProjectConfig.PROJECT_CONFIG, | |
| "[label \"Foo\"]\n function = INVALID"); | |
| PushOneCommit.Result r = push.to(RefNames.REFS_CONFIG); | |
| r.assertErrorStatus( | |
| String.format("commit %s: invalid project configuration", abbreviateName(r.getCommit()))); | |
| r.assertMessage( | |
| String.format( | |
| "ERROR: commit %s: invalid project configuration:\n" | |
| + "ERROR: commit %s: project.config: Invalid function for label \"foo\"." | |
| + " Valid names are: NoBlock, NoOp, PatchSetLock", | |
| abbreviateName(r.getCommit()), abbreviateName(r.getCommit()))); | |
| } | |
| @Test | |
| public void rejectCreatingLabelPermissionWithInvalidRange_minGreaterThanMax() throws Exception { | |
| fetchRefsMetaConfig(); | |
| PushOneCommit push = | |
| pushFactory.create( | |
| admin.newIdent(), | |
| testRepo, | |
| "Test Change", | |
| ImmutableMap.of( | |
| ProjectConfig.PROJECT_CONFIG, | |
| "[access \"refs/heads/*\"]\n label-Code-Review = 1..-1 group Registered-Users", | |
| GroupList.FILE_NAME, | |
| String.format("%s\tRegistered-Users", SystemGroupBackend.REGISTERED_USERS.get()))); | |
| PushOneCommit.Result r = push.to(RefNames.REFS_CONFIG); | |
| r.assertErrorStatus( | |
| String.format("commit %s: invalid project configuration", abbreviateName(r.getCommit()))); | |
| r.assertMessage( | |
| String.format( | |
| "ERROR: commit %s: invalid project configuration:\n" | |
| + "ERROR: commit %s: project.config: invalid rule in" | |
| + " access.refs/heads/*.label-Code-Review:" | |
| + " invalid range in rule: 1..-1 group Registered-Users", | |
| abbreviateName(r.getCommit()), abbreviateName(r.getCommit()))); | |
| } | |
| @Test | |
| public void rejectCreatingLabelPermissionWithInvalidRange_minSetMaxMissing() throws Exception { | |
| fetchRefsMetaConfig(); | |
| PushOneCommit push = | |
| pushFactory.create( | |
| admin.newIdent(), | |
| testRepo, | |
| "Test Change", | |
| ImmutableMap.of( | |
| ProjectConfig.PROJECT_CONFIG, | |
| "[access \"refs/heads/*\"]\n label-Code-Review = -1.. group Registered-Users", | |
| GroupList.FILE_NAME, | |
| String.format("%s\tRegistered-Users", SystemGroupBackend.REGISTERED_USERS.get()))); | |
| PushOneCommit.Result r = push.to(RefNames.REFS_CONFIG); | |
| r.assertErrorStatus( | |
| String.format("commit %s: invalid project configuration", abbreviateName(r.getCommit()))); | |
| r.assertMessage( | |
| String.format( | |
| "ERROR: commit %s: invalid project configuration:\n" | |
| + "ERROR: commit %s: project.config: invalid rule in" | |
| + " access.refs/heads/*.label-Code-Review:" | |
| + " invalid range in rule: -1.. group Registered-Users", | |
| abbreviateName(r.getCommit()), abbreviateName(r.getCommit()))); | |
| } | |
| @Test | |
| public void rejectCreatingLabelPermissionWithInvalidRange_maxSetMinMissing() throws Exception { | |
| fetchRefsMetaConfig(); | |
| PushOneCommit push = | |
| pushFactory.create( | |
| admin.newIdent(), | |
| testRepo, | |
| "Test Change", | |
| ImmutableMap.of( | |
| ProjectConfig.PROJECT_CONFIG, | |
| "[access \"refs/heads/*\"]\n label-Code-Review = ..1 group Registered-Users", | |
| GroupList.FILE_NAME, | |
| String.format("%s\tRegistered-Users", SystemGroupBackend.REGISTERED_USERS.get()))); | |
| PushOneCommit.Result r = push.to(RefNames.REFS_CONFIG); | |
| r.assertErrorStatus( | |
| String.format("commit %s: invalid project configuration", abbreviateName(r.getCommit()))); | |
| r.assertMessage( | |
| String.format( | |
| "ERROR: commit %s: invalid project configuration:\n" | |
| + "ERROR: commit %s: project.config: invalid rule in" | |
| + " access.refs/heads/*.label-Code-Review:" | |
| + " invalid range in rule: ..1 group Registered-Users", | |
| abbreviateName(r.getCommit()), abbreviateName(r.getCommit()))); | |
| } | |
| @Test | |
| public void rejectSettingCopyMinScore() throws Exception { | |
| testRejectSettingLabelFlag( | |
| LabelConfigValidator.KEY_COPY_MIN_SCORE, /* value= */ true, "is:MIN"); | |
| testRejectSettingLabelFlag( | |
| LabelConfigValidator.KEY_COPY_MIN_SCORE, /* value= */ false, "is:MIN"); | |
| } | |
| @Test | |
| public void rejectSettingCopyMaxScore() throws Exception { | |
| testRejectSettingLabelFlag( | |
| LabelConfigValidator.KEY_COPY_MAX_SCORE, /* value= */ true, "is:MAX"); | |
| testRejectSettingLabelFlag( | |
| LabelConfigValidator.KEY_COPY_MAX_SCORE, /* value= */ false, "is:MAX"); | |
| } | |
| @Test | |
| public void rejectSettingCopyAllScoresIfNoChange() throws Exception { | |
| testRejectSettingLabelFlag( | |
| LabelConfigValidator.KEY_COPY_ALL_SCORES_IF_NO_CHANGE, | |
| /* value= */ true, | |
| "changekind:NO_CHANGE"); | |
| testRejectSettingLabelFlag( | |
| LabelConfigValidator.KEY_COPY_ALL_SCORES_IF_NO_CHANGE, | |
| /* value= */ false, | |
| "changekind:NO_CHANGE"); | |
| } | |
| @Test | |
| public void rejectSettingCopyAllScoresIfNoCodeChange() throws Exception { | |
| testRejectSettingLabelFlag( | |
| LabelConfigValidator.KEY_COPY_ALL_SCORES_IF_NO_CODE_CHANGE, | |
| /* value= */ true, | |
| "changekind:NO_CODE_CHANGE"); | |
| testRejectSettingLabelFlag( | |
| LabelConfigValidator.KEY_COPY_ALL_SCORES_IF_NO_CODE_CHANGE, | |
| /* value= */ false, | |
| "changekind:NO_CODE_CHANGE"); | |
| } | |
| @Test | |
| public void rejectSettingCopyAllScoresOnMergeFirstParentUpdate() throws Exception { | |
| testRejectSettingLabelFlag( | |
| LabelConfigValidator.KEY_COPY_ALL_SCORES_ON_MERGE_FIRST_PARENT_UPDATE, | |
| /* value= */ true, | |
| "changekind:MERGE_FIRST_PARENT_UPDATE"); | |
| testRejectSettingLabelFlag( | |
| LabelConfigValidator.KEY_COPY_ALL_SCORES_ON_MERGE_FIRST_PARENT_UPDATE, | |
| /* value= */ false, | |
| "changekind:MERGE_FIRST_PARENT_UPDATE"); | |
| } | |
| @Test | |
| public void rejectSettingCopyAllScoresOnTrivialRebase() throws Exception { | |
| testRejectSettingLabelFlag( | |
| LabelConfigValidator.KEY_COPY_ALL_SCORES_ON_TRIVIAL_REBASE, | |
| /* value= */ true, | |
| "changekind:TRIVIAL_REBASE"); | |
| testRejectSettingLabelFlag( | |
| LabelConfigValidator.KEY_COPY_ALL_SCORES_ON_TRIVIAL_REBASE, | |
| /* value= */ false, | |
| "changekind:TRIVIAL_REBASE"); | |
| } | |
| @Test | |
| public void rejectSettingCopyAllScoresIfListOfFilesDidNotChange() throws Exception { | |
| testRejectSettingLabelFlag( | |
| LabelConfigValidator.KEY_COPY_ALL_SCORES_IF_LIST_OF_FILES_DID_NOT_CHANGE, | |
| /* value= */ true, | |
| "has:unchanged-files"); | |
| testRejectSettingLabelFlag( | |
| LabelConfigValidator.KEY_COPY_ALL_SCORES_IF_LIST_OF_FILES_DID_NOT_CHANGE, | |
| /* value= */ false, | |
| "has:unchanged-files"); | |
| } | |
| private void testRejectSettingLabelFlag( | |
| String key, boolean value, String expectedPredicateSuggestion) throws Exception { | |
| fetchRefsMetaConfig(); | |
| PushOneCommit push = | |
| pushFactory.create( | |
| admin.newIdent(), | |
| testRepo, | |
| "Test Change", | |
| ProjectConfig.PROJECT_CONFIG, | |
| String.format("[label \"Foo\"]\n %s = %s", key, value)); | |
| PushOneCommit.Result r = push.to(RefNames.REFS_CONFIG); | |
| r.assertErrorStatus( | |
| String.format( | |
| "invalid %s file in revision %s", ProjectConfig.PROJECT_CONFIG, r.getCommit().name())); | |
| r.assertMessage( | |
| String.format( | |
| "ERROR: commit %s: Parameter 'label.Foo.%s' is deprecated and cannot be set," | |
| + " use '%s' in 'label.Foo.copyCondition' instead.", | |
| abbreviateName(r.getCommit()), key, expectedPredicateSuggestion)); | |
| } | |
| @Test | |
| public void rejectSettingCopyValues() throws Exception { | |
| fetchRefsMetaConfig(); | |
| PushOneCommit push = | |
| pushFactory.create( | |
| admin.newIdent(), | |
| testRepo, | |
| "Test Change", | |
| ProjectConfig.PROJECT_CONFIG, | |
| String.format( | |
| "[label \"Foo\"]\n %s = 1\n %s = 2", | |
| LabelConfigValidator.KEY_COPY_VALUE, LabelConfigValidator.KEY_COPY_VALUE)); | |
| PushOneCommit.Result r = push.to(RefNames.REFS_CONFIG); | |
| r.assertErrorStatus( | |
| String.format( | |
| "invalid %s file in revision %s", ProjectConfig.PROJECT_CONFIG, r.getCommit().name())); | |
| r.assertMessage( | |
| String.format( | |
| "ERROR: commit %s: Parameter 'label.Foo.%s' is deprecated and cannot be set," | |
| + " use 'is:<copy-value>' in 'label.Foo.copyCondition' instead.", | |
| abbreviateName(r.getCommit()), LabelConfigValidator.KEY_COPY_VALUE)); | |
| } | |
| @Test | |
| public void rejectChangingCopyAnyScore() throws Exception { | |
| testRejectChangingLabelFlag( | |
| LabelConfigValidator.KEY_COPY_ANY_SCORE, /* value= */ true, "is:ANY"); | |
| testRejectChangingLabelFlag( | |
| LabelConfigValidator.KEY_COPY_ANY_SCORE, /* value= */ false, "is:ANY"); | |
| } | |
| @Test | |
| public void rejectChangingCopyMinScore() throws Exception { | |
| testRejectChangingLabelFlag( | |
| LabelConfigValidator.KEY_COPY_MIN_SCORE, /* value= */ true, "is:MIN"); | |
| testRejectChangingLabelFlag( | |
| LabelConfigValidator.KEY_COPY_MIN_SCORE, /* value= */ false, "is:MIN"); | |
| } | |
| @Test | |
| public void rejectChangingCopyMaxScore() throws Exception { | |
| testRejectChangingLabelFlag( | |
| LabelConfigValidator.KEY_COPY_MAX_SCORE, /* value= */ true, "is:MAX"); | |
| testRejectChangingLabelFlag( | |
| LabelConfigValidator.KEY_COPY_MAX_SCORE, /* value= */ false, "is:MAX"); | |
| } | |
| @Test | |
| public void rejectChangingCopyAllScoresIfNoChange() throws Exception { | |
| testRejectChangingLabelFlag( | |
| LabelConfigValidator.KEY_COPY_ALL_SCORES_IF_NO_CHANGE, | |
| /* value= */ true, | |
| "changekind:NO_CHANGE"); | |
| testRejectChangingLabelFlag( | |
| LabelConfigValidator.KEY_COPY_ALL_SCORES_IF_NO_CHANGE, | |
| /* value= */ false, | |
| "changekind:NO_CHANGE"); | |
| } | |
| @Test | |
| public void rejectChangingCopyAllScoresIfNoCodeChange() throws Exception { | |
| testRejectChangingLabelFlag( | |
| LabelConfigValidator.KEY_COPY_ALL_SCORES_IF_NO_CODE_CHANGE, | |
| /* value= */ true, | |
| "changekind:NO_CODE_CHANGE"); | |
| testRejectChangingLabelFlag( | |
| LabelConfigValidator.KEY_COPY_ALL_SCORES_IF_NO_CODE_CHANGE, | |
| /* value= */ false, | |
| "changekind:NO_CODE_CHANGE"); | |
| } | |
| @Test | |
| public void rejectChangingCopyAllScoresOnMergeFirstParentUpdate() throws Exception { | |
| testRejectChangingLabelFlag( | |
| LabelConfigValidator.KEY_COPY_ALL_SCORES_ON_MERGE_FIRST_PARENT_UPDATE, | |
| /* value= */ true, | |
| "changekind:MERGE_FIRST_PARENT_UPDATE"); | |
| testRejectChangingLabelFlag( | |
| LabelConfigValidator.KEY_COPY_ALL_SCORES_ON_MERGE_FIRST_PARENT_UPDATE, | |
| /* value= */ false, | |
| "changekind:MERGE_FIRST_PARENT_UPDATE"); | |
| } | |
| @Test | |
| public void rejectChangingCopyAllScoresOnTrivialRebase() throws Exception { | |
| testRejectChangingLabelFlag( | |
| LabelConfigValidator.KEY_COPY_ALL_SCORES_ON_TRIVIAL_REBASE, | |
| /* value= */ true, | |
| "changekind:TRIVIAL_REBASE"); | |
| testRejectChangingLabelFlag( | |
| LabelConfigValidator.KEY_COPY_ALL_SCORES_ON_TRIVIAL_REBASE, | |
| /* value= */ false, | |
| "changekind:TRIVIAL_REBASE"); | |
| } | |
| @Test | |
| public void rejectChangingCopyAllScoresIfListOfFilesDidNotChange() throws Exception { | |
| testRejectChangingLabelFlag( | |
| LabelConfigValidator.KEY_COPY_ALL_SCORES_IF_LIST_OF_FILES_DID_NOT_CHANGE, | |
| /* value= */ true, | |
| "has:unchanged-files"); | |
| testRejectChangingLabelFlag( | |
| LabelConfigValidator.KEY_COPY_ALL_SCORES_IF_LIST_OF_FILES_DID_NOT_CHANGE, | |
| /* value= */ false, | |
| "has:unchanged-files"); | |
| } | |
| private void testRejectChangingLabelFlag( | |
| String key, boolean value, String expectedPredicateSuggestion) throws Exception { | |
| try (TestRepository<Repository> testRepo = | |
| new TestRepository<>(repoManager.openRepository(project))) { | |
| testRepo | |
| .branch(RefNames.REFS_CONFIG) | |
| .commit() | |
| .add( | |
| ProjectConfig.PROJECT_CONFIG, | |
| String.format("[label \"Foo\"]\n %s = %s", key, !value)) | |
| .parent(projectOperations.project(project).getHead(RefNames.REFS_CONFIG)) | |
| .create(); | |
| } | |
| testRejectSettingLabelFlag(key, value, expectedPredicateSuggestion); | |
| } | |
| @Test | |
| public void rejectChangingCopyValues() throws Exception { | |
| try (TestRepository<Repository> testRepo = | |
| new TestRepository<>(repoManager.openRepository(project))) { | |
| testRepo | |
| .branch(RefNames.REFS_CONFIG) | |
| .commit() | |
| .add( | |
| ProjectConfig.PROJECT_CONFIG, | |
| String.format( | |
| "[label \"Foo\"]\n %s = 1\n %s = 2", | |
| LabelConfigValidator.KEY_COPY_VALUE, LabelConfigValidator.KEY_COPY_VALUE)) | |
| .parent(projectOperations.project(project).getHead(RefNames.REFS_CONFIG)) | |
| .create(); | |
| } | |
| fetchRefsMetaConfig(); | |
| PushOneCommit push = | |
| pushFactory.create( | |
| admin.newIdent(), | |
| testRepo, | |
| "Test Change", | |
| ProjectConfig.PROJECT_CONFIG, | |
| String.format( | |
| "[label \"Foo\"]\n %s = -1\n %s = -2", | |
| LabelConfigValidator.KEY_COPY_VALUE, LabelConfigValidator.KEY_COPY_VALUE)); | |
| PushOneCommit.Result r = push.to(RefNames.REFS_CONFIG); | |
| r.assertErrorStatus( | |
| String.format( | |
| "invalid %s file in revision %s", ProjectConfig.PROJECT_CONFIG, r.getCommit().name())); | |
| r.assertMessage( | |
| String.format( | |
| "ERROR: commit %s: Parameter 'label.Foo.%s' is deprecated and cannot be set," | |
| + " use 'is:<copy-value>' in 'label.Foo.copyCondition' instead.", | |
| abbreviateName(r.getCommit()), LabelConfigValidator.KEY_COPY_VALUE)); | |
| } | |
| @Test | |
| public void rejectSubmitRequirement_duplicateDescriptionKeys() throws Exception { | |
| fetchRefsMetaConfig(); | |
| PushOneCommit push = | |
| pushFactory.create( | |
| admin.newIdent(), | |
| testRepo, | |
| "Test Change", | |
| ProjectConfig.PROJECT_CONFIG, | |
| "[submit-requirement \"Foo\"]\n" | |
| + " description = description 1\n " | |
| + " submittableIf = label:Code-Review=MAX\n" | |
| + "[submit-requirement \"Foo\"]\n" | |
| + " description = description 2\n"); | |
| PushOneCommit.Result r = push.to(RefNames.REFS_CONFIG); | |
| r.assertErrorStatus( | |
| String.format("commit %s: invalid project configuration", abbreviateName(r.getCommit()))); | |
| r.assertMessage( | |
| String.format( | |
| "ERROR: commit %s: project.config: multiple definitions of description" | |
| + " for submit requirement 'foo'", | |
| abbreviateName(r.getCommit()))); | |
| } | |
| @Test | |
| public void rejectSubmitRequirement_duplicateApplicableIfKeys() throws Exception { | |
| fetchRefsMetaConfig(); | |
| PushOneCommit push = | |
| pushFactory.create( | |
| admin.newIdent(), | |
| testRepo, | |
| "Test Change", | |
| ProjectConfig.PROJECT_CONFIG, | |
| "[submit-requirement \"Foo\"]\n " | |
| + " applicableIf = is:true\n " | |
| + " submittableIf = label:Code-Review=MAX\n" | |
| + "[submit-requirement \"Foo\"]\n" | |
| + " applicableIf = is:false\n"); | |
| PushOneCommit.Result r = push.to(RefNames.REFS_CONFIG); | |
| r.assertErrorStatus( | |
| String.format("commit %s: invalid project configuration", abbreviateName(r.getCommit()))); | |
| r.assertMessage( | |
| String.format( | |
| "ERROR: commit %s: project.config: multiple definitions of applicableif" | |
| + " for submit requirement 'foo'", | |
| abbreviateName(r.getCommit()))); | |
| } | |
| @Test | |
| public void rejectSubmitRequirement_duplicateSubmittableIfKeys() throws Exception { | |
| fetchRefsMetaConfig(); | |
| PushOneCommit push = | |
| pushFactory.create( | |
| admin.newIdent(), | |
| testRepo, | |
| "Test Change", | |
| ProjectConfig.PROJECT_CONFIG, | |
| "[submit-requirement \"Foo\"]\n" | |
| + " submittableIf = label:Code-Review=MAX\n" | |
| + "[submit-requirement \"Foo\"]\n" | |
| + " submittableIf = label:Code-Review=MIN\n"); | |
| PushOneCommit.Result r = push.to(RefNames.REFS_CONFIG); | |
| r.assertErrorStatus( | |
| String.format("commit %s: invalid project configuration", abbreviateName(r.getCommit()))); | |
| r.assertMessage( | |
| String.format( | |
| "ERROR: commit %s: project.config: multiple definitions of submittableif" | |
| + " for submit requirement 'foo'", | |
| abbreviateName(r.getCommit()))); | |
| } | |
| @Test | |
| public void rejectSubmitRequirement_duplicateOverrideIfKeys() throws Exception { | |
| fetchRefsMetaConfig(); | |
| PushOneCommit push = | |
| pushFactory.create( | |
| admin.newIdent(), | |
| testRepo, | |
| "Test Change", | |
| ProjectConfig.PROJECT_CONFIG, | |
| "[submit-requirement \"Foo\"]\n" | |
| + " overrideIf = is:true\n " | |
| + " submittableIf = label:Code-Review=MAX\n" | |
| + "[submit-requirement \"Foo\"]\n" | |
| + " overrideIf = is:false\n"); | |
| PushOneCommit.Result r = push.to(RefNames.REFS_CONFIG); | |
| r.assertErrorStatus( | |
| String.format("commit %s: invalid project configuration", abbreviateName(r.getCommit()))); | |
| r.assertMessage( | |
| String.format( | |
| "ERROR: commit %s: project.config: multiple definitions of overrideif" | |
| + " for submit requirement 'foo'", | |
| abbreviateName(r.getCommit()))); | |
| } | |
| @Test | |
| public void rejectSubmitRequirement_duplicateCanOverrideInChildProjectsKey() throws Exception { | |
| fetchRefsMetaConfig(); | |
| PushOneCommit push = | |
| pushFactory.create( | |
| admin.newIdent(), | |
| testRepo, | |
| "Test Change", | |
| ProjectConfig.PROJECT_CONFIG, | |
| "[submit-requirement \"Foo\"]\n" | |
| + " canOverrideInChildProjects = true\n" | |
| + " submittableIf = label:Code-Review=MAX\n" | |
| + "[submit-requirement \"Foo\"]\n " | |
| + " canOverrideInChildProjects = false\n"); | |
| PushOneCommit.Result r = push.to(RefNames.REFS_CONFIG); | |
| r.assertErrorStatus( | |
| String.format("commit %s: invalid project configuration", abbreviateName(r.getCommit()))); | |
| r.assertMessage( | |
| String.format( | |
| "ERROR: commit %s: project.config: multiple definitions of canoverrideinchildprojects" | |
| + " for submit requirement 'foo'", | |
| abbreviateName(r.getCommit()))); | |
| } | |
| @Test | |
| public void submitRequirementsAreParsed_forExistingDuplicateDefinitions() throws Exception { | |
| // Duplicate submit requirement definitions are rejected on config change uploads. For setups | |
| // already containing duplicate SR definitions, the server is able to parse the "submit | |
| // requirements correctly" | |
| RevCommit revision; | |
| // Commit a change to the project config, bypassing server validation. | |
| try (TestRepository<Repository> testRepo = | |
| new TestRepository<>(repoManager.openRepository(project))) { | |
| revision = | |
| testRepo | |
| .branch(RefNames.REFS_CONFIG) | |
| .commit() | |
| .add( | |
| ProjectConfig.PROJECT_CONFIG, | |
| "[submit-requirement \"Foo\"]\n" | |
| + " canOverrideInChildProjects = true\n" | |
| + " submittableIf = label:Code-Review=MAX\n" | |
| + "[submit-requirement \"Foo\"]\n " | |
| + " canOverrideInChildProjects = false\n") | |
| .parent(projectOperations.project(project).getHead(RefNames.REFS_CONFIG)) | |
| .create(); | |
| } | |
| try (Repository git = repoManager.openRepository(project)) { | |
| // Server is able to parse the config. | |
| ProjectConfig cfg = projectConfigFactory.create(project); | |
| cfg.load(git, revision); | |
| // One of the two definitions takes precedence and overrides the other. | |
| assertThat(cfg.getSubmitRequirementSections()) | |
| .containsExactly( | |
| "Foo", | |
| SubmitRequirement.builder() | |
| .setName("Foo") | |
| .setAllowOverrideInChildProjects(false) | |
| .setSubmittabilityExpression( | |
| SubmitRequirementExpression.create("label:Code-Review=MAX")) | |
| .build()); | |
| } | |
| } | |
| @Test | |
| public void testRejectChangingLabelFunction_toMaxWithBlock() throws Exception { | |
| testChangingLabelFunction( | |
| /* initialLabelFunction= */ LabelFunction.NO_BLOCK, | |
| /* newLabelFunction= */ LabelFunction.MAX_WITH_BLOCK, | |
| /* errorMessage= */ String.format( | |
| "Value '%s' of 'label.foo.function' is not allowed and cannot be set." | |
| + " Label functions can only be set to {no_block, no_op, patch_set_lock}." | |
| + " Use submit requirements instead of label functions.", | |
| LabelFunction.MAX_WITH_BLOCK.getFunctionName())); | |
| } | |
| @Test | |
| public void testRejectChangingLabelFunction_toMaxNoBlock() throws Exception { | |
| testChangingLabelFunction( | |
| /* initialLabelFunction= */ LabelFunction.NO_BLOCK, | |
| /* newLabelFunction= */ LabelFunction.MAX_NO_BLOCK, | |
| /* errorMessage= */ String.format( | |
| "Value '%s' of 'label.foo.function' is not allowed and cannot be set." | |
| + " Label functions can only be set to {no_block, no_op, patch_set_lock}." | |
| + " Use submit requirements instead of label functions.", | |
| LabelFunction.MAX_NO_BLOCK.getFunctionName())); | |
| } | |
| @Test | |
| public void testRejectChangingLabelFunction_toAnyWithBlock() throws Exception { | |
| testChangingLabelFunction( | |
| /* initialLabelFunction= */ LabelFunction.NO_BLOCK, | |
| /* newLabelFunction= */ LabelFunction.ANY_WITH_BLOCK, | |
| /* errorMessage= */ String.format( | |
| "Value '%s' of 'label.foo.function' is not allowed and cannot be set." | |
| + " Label functions can only be set to {no_block, no_op, patch_set_lock}." | |
| + " Use submit requirements instead of label functions.", | |
| LabelFunction.ANY_WITH_BLOCK.getFunctionName())); | |
| } | |
| @Test | |
| public void testChangingLabelFunction_toNoBlock() throws Exception { | |
| testChangingLabelFunction( | |
| /* initialLabelFunction= */ LabelFunction.MAX_WITH_BLOCK, | |
| /* newLabelFunction= */ LabelFunction.NO_BLOCK, | |
| /* errorMessage= */ null); | |
| } | |
| @Test | |
| public void testChangingLabelFunction_toNoOp() throws Exception { | |
| testChangingLabelFunction( | |
| /* initialLabelFunction= */ LabelFunction.MAX_WITH_BLOCK, | |
| /* newLabelFunction= */ LabelFunction.NO_OP, | |
| /* errorMessage= */ null); | |
| } | |
| @Test | |
| public void testChangingLabelFunction_toPatchSetLock() throws Exception { | |
| testChangingLabelFunction( | |
| /* initialLabelFunction= */ LabelFunction.MAX_WITH_BLOCK, | |
| /* newLabelFunction= */ LabelFunction.PATCH_SET_LOCK, | |
| /* errorMessage= */ null); | |
| } | |
| @Test | |
| public void testRejectRemovingLabelFunction() throws Exception { | |
| testChangingLabelFunction( | |
| /* initialLabelFunction= */ LabelFunction.MAX_WITH_BLOCK, | |
| /* newLabelFunction= */ null, | |
| /* errorMessage= */ String.format( | |
| "Cannot delete '%s.%s.%s'." | |
| + " Label functions can only be set to {%s, %s, %s}." | |
| + " Use submit requirements instead of label functions.", | |
| ProjectConfig.LABEL, | |
| "Foo", | |
| ProjectConfig.KEY_FUNCTION, | |
| LabelFunction.NO_BLOCK, | |
| LabelFunction.NO_OP, | |
| LabelFunction.PATCH_SET_LOCK)); | |
| } | |
| private void testChangingLabelFunction( | |
| LabelFunction initialLabelFunction, | |
| @Nullable LabelFunction newLabelFunction, | |
| @Nullable String errorMessage) | |
| throws Exception { | |
| try (TestRepository<Repository> testRepo = | |
| new TestRepository<>(repoManager.openRepository(project))) { | |
| testRepo | |
| .branch(RefNames.REFS_CONFIG) | |
| .commit() | |
| .add( | |
| ProjectConfig.PROJECT_CONFIG, | |
| String.format( | |
| "[label \"Foo\"]\n %s = %s\n", | |
| ProjectConfig.KEY_FUNCTION, initialLabelFunction.getFunctionName())) | |
| .parent(projectOperations.project(project).getHead(RefNames.REFS_CONFIG)) | |
| .create(); | |
| } | |
| fetchRefsMetaConfig(); | |
| PushOneCommit push = | |
| pushFactory.create( | |
| admin.newIdent(), | |
| testRepo, | |
| "Test Change", | |
| ProjectConfig.PROJECT_CONFIG, | |
| newLabelFunction == null | |
| ? "[label \"Foo\"]\n" | |
| : String.format( | |
| "[label \"Foo\"]\n %s = %s\n", | |
| ProjectConfig.KEY_FUNCTION, newLabelFunction.getFunctionName())); | |
| PushOneCommit.Result r = push.to(RefNames.REFS_CONFIG); | |
| if (errorMessage == null) { | |
| r.assertOkStatus(); | |
| return; | |
| } | |
| r.assertErrorStatus( | |
| String.format( | |
| "invalid %s file in revision %s", ProjectConfig.PROJECT_CONFIG, r.getCommit().name())); | |
| r.assertMessage(errorMessage); | |
| } | |
| @Test | |
| public void unsetCopyAnyScore() throws Exception { | |
| testUnsetLabelFlag(LabelConfigValidator.KEY_COPY_ANY_SCORE, /* previousValue= */ true); | |
| testUnsetLabelFlag(LabelConfigValidator.KEY_COPY_ANY_SCORE, /* previousValue= */ false); | |
| } | |
| @Test | |
| public void unsetCopyMinScore() throws Exception { | |
| testUnsetLabelFlag(LabelConfigValidator.KEY_COPY_MIN_SCORE, /* previousValue= */ true); | |
| testUnsetLabelFlag(LabelConfigValidator.KEY_COPY_MIN_SCORE, /* previousValue= */ false); | |
| } | |
| @Test | |
| public void unsetCopyMaxScore() throws Exception { | |
| testUnsetLabelFlag(LabelConfigValidator.KEY_COPY_MAX_SCORE, /* previousValue= */ true); | |
| testUnsetLabelFlag(LabelConfigValidator.KEY_COPY_MAX_SCORE, /* previousValue= */ false); | |
| } | |
| @Test | |
| public void unsetCopyAllScoresIfNoChange() throws Exception { | |
| testUnsetLabelFlag( | |
| LabelConfigValidator.KEY_COPY_ALL_SCORES_IF_NO_CHANGE, /* previousValue= */ true); | |
| testUnsetLabelFlag( | |
| LabelConfigValidator.KEY_COPY_ALL_SCORES_IF_NO_CHANGE, /* previousValue= */ false); | |
| } | |
| @Test | |
| public void unsetCopyAllScoresIfNoCodeChange() throws Exception { | |
| testUnsetLabelFlag( | |
| LabelConfigValidator.KEY_COPY_ALL_SCORES_IF_NO_CODE_CHANGE, /* previousValue= */ true); | |
| testUnsetLabelFlag( | |
| LabelConfigValidator.KEY_COPY_ALL_SCORES_IF_NO_CODE_CHANGE, /* previousValue= */ false); | |
| } | |
| @Test | |
| public void unsetCopyAllScoresOnMergeFirstParentUpdate() throws Exception { | |
| testUnsetLabelFlag( | |
| LabelConfigValidator.KEY_COPY_ALL_SCORES_ON_MERGE_FIRST_PARENT_UPDATE, | |
| /* previousValue= */ true); | |
| testUnsetLabelFlag( | |
| LabelConfigValidator.KEY_COPY_ALL_SCORES_ON_MERGE_FIRST_PARENT_UPDATE, | |
| /* previousValue= */ false); | |
| } | |
| @Test | |
| public void unsetCopyAllScoresOnTrivialRebase() throws Exception { | |
| testUnsetLabelFlag( | |
| LabelConfigValidator.KEY_COPY_ALL_SCORES_ON_TRIVIAL_REBASE, /* previousValue= */ true); | |
| testUnsetLabelFlag( | |
| LabelConfigValidator.KEY_COPY_ALL_SCORES_ON_TRIVIAL_REBASE, /* previousValue= */ false); | |
| } | |
| @Test | |
| public void unsetCopyAllScoresIfListOfFilesDidNotChange() throws Exception { | |
| testUnsetLabelFlag( | |
| LabelConfigValidator.KEY_COPY_ALL_SCORES_IF_LIST_OF_FILES_DID_NOT_CHANGE, | |
| /* previousValue= */ true); | |
| testUnsetLabelFlag( | |
| LabelConfigValidator.KEY_COPY_ALL_SCORES_IF_LIST_OF_FILES_DID_NOT_CHANGE, | |
| /* previousValue= */ false); | |
| } | |
| private void testUnsetLabelFlag(String key, boolean previousValue) throws Exception { | |
| try (TestRepository<Repository> testRepo = | |
| new TestRepository<>(repoManager.openRepository(project))) { | |
| testRepo | |
| .branch(RefNames.REFS_CONFIG) | |
| .commit() | |
| .add( | |
| ProjectConfig.PROJECT_CONFIG, | |
| String.format("[label \"Foo\"]\n %s = %s", key, previousValue)) | |
| .parent(projectOperations.project(project).getHead(RefNames.REFS_CONFIG)) | |
| .create(); | |
| } | |
| fetchRefsMetaConfig(); | |
| PushOneCommit push = | |
| pushFactory.create( | |
| admin.newIdent(), | |
| testRepo, | |
| "Test Change", | |
| ProjectConfig.PROJECT_CONFIG, | |
| String.format("[label \"Foo\"]\n otherKey = value")); | |
| PushOneCommit.Result r = push.to(RefNames.REFS_CONFIG); | |
| r.assertOkStatus(); | |
| } | |
| @Test | |
| public void unsetCopyValues() throws Exception { | |
| try (TestRepository<Repository> testRepo = | |
| new TestRepository<>(repoManager.openRepository(project))) { | |
| testRepo | |
| .branch(RefNames.REFS_CONFIG) | |
| .commit() | |
| .add( | |
| ProjectConfig.PROJECT_CONFIG, | |
| String.format( | |
| "[label \"Foo\"]\n %s = 1\n %s = 2", | |
| LabelConfigValidator.KEY_COPY_VALUE, LabelConfigValidator.KEY_COPY_VALUE)) | |
| .parent(projectOperations.project(project).getHead(RefNames.REFS_CONFIG)) | |
| .create(); | |
| } | |
| fetchRefsMetaConfig(); | |
| PushOneCommit push = | |
| pushFactory.create( | |
| admin.newIdent(), | |
| testRepo, | |
| "Test Change", | |
| ProjectConfig.PROJECT_CONFIG, | |
| String.format("[label \"Foo\"]\n otherKey = value")); | |
| PushOneCommit.Result r = push.to(RefNames.REFS_CONFIG); | |
| r.assertOkStatus(); | |
| } | |
| @Test | |
| public void keepCopyAnyScoreUnchanged() throws Exception { | |
| testKeepLabelFlagUnchanged(LabelConfigValidator.KEY_COPY_ANY_SCORE, /* value= */ true); | |
| testKeepLabelFlagUnchanged(LabelConfigValidator.KEY_COPY_ANY_SCORE, /* value= */ false); | |
| } | |
| @Test | |
| public void keepCopyMinScoreUnchanged() throws Exception { | |
| testKeepLabelFlagUnchanged(LabelConfigValidator.KEY_COPY_MIN_SCORE, /* value= */ true); | |
| testKeepLabelFlagUnchanged(LabelConfigValidator.KEY_COPY_MIN_SCORE, /* value= */ false); | |
| } | |
| @Test | |
| public void keepCopyMaxScoreUnchanged() throws Exception { | |
| testKeepLabelFlagUnchanged(LabelConfigValidator.KEY_COPY_MAX_SCORE, /* value= */ true); | |
| testKeepLabelFlagUnchanged(LabelConfigValidator.KEY_COPY_MAX_SCORE, /* value= */ false); | |
| } | |
| @Test | |
| public void keepCopyAllScoresIfNoChangeUnchanged() throws Exception { | |
| testKeepLabelFlagUnchanged( | |
| LabelConfigValidator.KEY_COPY_ALL_SCORES_IF_NO_CHANGE, /* value= */ true); | |
| testKeepLabelFlagUnchanged( | |
| LabelConfigValidator.KEY_COPY_ALL_SCORES_IF_NO_CHANGE, /* value= */ false); | |
| } | |
| @Test | |
| public void keepCopyAllScoresIfNoCodeChangeUnchanged() throws Exception { | |
| testKeepLabelFlagUnchanged( | |
| LabelConfigValidator.KEY_COPY_ALL_SCORES_IF_NO_CODE_CHANGE, /* value= */ true); | |
| testKeepLabelFlagUnchanged( | |
| LabelConfigValidator.KEY_COPY_ALL_SCORES_IF_NO_CODE_CHANGE, /* value= */ false); | |
| } | |
| @Test | |
| public void keepCopyAllScoresOnMergeFirstParentUpdateUnchanged() throws Exception { | |
| testKeepLabelFlagUnchanged( | |
| LabelConfigValidator.KEY_COPY_ALL_SCORES_ON_MERGE_FIRST_PARENT_UPDATE, /* value= */ true); | |
| testKeepLabelFlagUnchanged( | |
| LabelConfigValidator.KEY_COPY_ALL_SCORES_ON_MERGE_FIRST_PARENT_UPDATE, /* value= */ false); | |
| } | |
| @Test | |
| public void keepCopyAllScoresOnTrivialRebaseUnchanged() throws Exception { | |
| testKeepLabelFlagUnchanged( | |
| LabelConfigValidator.KEY_COPY_ALL_SCORES_ON_TRIVIAL_REBASE, /* value= */ true); | |
| testKeepLabelFlagUnchanged( | |
| LabelConfigValidator.KEY_COPY_ALL_SCORES_ON_TRIVIAL_REBASE, /* value= */ false); | |
| } | |
| @Test | |
| public void keepCopyAllScoresIfListOfFilesDidNotChangeUnchanged() throws Exception { | |
| testKeepLabelFlagUnchanged( | |
| LabelConfigValidator.KEY_COPY_ALL_SCORES_IF_LIST_OF_FILES_DID_NOT_CHANGE, | |
| /* value= */ true); | |
| testKeepLabelFlagUnchanged( | |
| LabelConfigValidator.KEY_COPY_ALL_SCORES_IF_LIST_OF_FILES_DID_NOT_CHANGE, | |
| /* value= */ false); | |
| } | |
| private void testKeepLabelFlagUnchanged(String key, boolean value) throws Exception { | |
| try (TestRepository<Repository> testRepo = | |
| new TestRepository<>(repoManager.openRepository(project))) { | |
| testRepo | |
| .branch(RefNames.REFS_CONFIG) | |
| .commit() | |
| .add( | |
| ProjectConfig.PROJECT_CONFIG, String.format("[label \"Foo\"]\n %s = %s", key, value)) | |
| .parent(projectOperations.project(project).getHead(RefNames.REFS_CONFIG)) | |
| .create(); | |
| } | |
| fetchRefsMetaConfig(); | |
| PushOneCommit push = | |
| pushFactory.create( | |
| admin.newIdent(), | |
| testRepo, | |
| "Test Change", | |
| ProjectConfig.PROJECT_CONFIG, | |
| String.format("[label \"Foo\"]\n %s = %s\n otherKey = value", key, value)); | |
| PushOneCommit.Result r = push.to(RefNames.REFS_CONFIG); | |
| r.assertOkStatus(); | |
| } | |
| @Test | |
| public void keepCopyValuesUnchanged() throws Exception { | |
| try (TestRepository<Repository> testRepo = | |
| new TestRepository<>(repoManager.openRepository(project))) { | |
| testRepo | |
| .branch(RefNames.REFS_CONFIG) | |
| .commit() | |
| .add( | |
| ProjectConfig.PROJECT_CONFIG, | |
| String.format( | |
| "[label \"Foo\"]\n %s = 1\n %s = 2", | |
| LabelConfigValidator.KEY_COPY_VALUE, LabelConfigValidator.KEY_COPY_VALUE)) | |
| .parent(projectOperations.project(project).getHead(RefNames.REFS_CONFIG)) | |
| .create(); | |
| } | |
| fetchRefsMetaConfig(); | |
| PushOneCommit push = | |
| pushFactory.create( | |
| admin.newIdent(), | |
| testRepo, | |
| "Test Change", | |
| ProjectConfig.PROJECT_CONFIG, | |
| String.format( | |
| "[label \"Foo\"]\n %s = 1\n %s = 2\n otherKey = value", | |
| LabelConfigValidator.KEY_COPY_VALUE, LabelConfigValidator.KEY_COPY_VALUE)); | |
| PushOneCommit.Result r = push.to(RefNames.REFS_CONFIG); | |
| r.assertOkStatus(); | |
| } | |
| @Test | |
| public void keepCopyValuesUnchanged_differentOrder() throws Exception { | |
| try (TestRepository<Repository> testRepo = | |
| new TestRepository<>(repoManager.openRepository(project))) { | |
| testRepo | |
| .branch(RefNames.REFS_CONFIG) | |
| .commit() | |
| .add( | |
| ProjectConfig.PROJECT_CONFIG, | |
| String.format( | |
| "[label \"Foo\"]\n %s = 1\n %s = 2", | |
| LabelConfigValidator.KEY_COPY_VALUE, LabelConfigValidator.KEY_COPY_VALUE)) | |
| .parent(projectOperations.project(project).getHead(RefNames.REFS_CONFIG)) | |
| .create(); | |
| } | |
| fetchRefsMetaConfig(); | |
| PushOneCommit push = | |
| pushFactory.create( | |
| admin.newIdent(), | |
| testRepo, | |
| "Test Change", | |
| ProjectConfig.PROJECT_CONFIG, | |
| String.format( | |
| "[label \"Foo\"]\n %s = 2\n %s = 1", | |
| LabelConfigValidator.KEY_COPY_VALUE, LabelConfigValidator.KEY_COPY_VALUE)); | |
| PushOneCommit.Result r = push.to(RefNames.REFS_CONFIG); | |
| r.assertOkStatus(); | |
| } | |
| @Test | |
| public void rejectMultipleLabelFlags() throws Exception { | |
| fetchRefsMetaConfig(); | |
| PushOneCommit push = | |
| pushFactory.create( | |
| admin.newIdent(), | |
| testRepo, | |
| "Test Change", | |
| ProjectConfig.PROJECT_CONFIG, | |
| String.format( | |
| "[label \"Foo\"]\n %s = true\n %s = true", | |
| LabelConfigValidator.KEY_COPY_MIN_SCORE, LabelConfigValidator.KEY_COPY_MAX_SCORE)); | |
| PushOneCommit.Result r = push.to(RefNames.REFS_CONFIG); | |
| r.assertErrorStatus( | |
| String.format( | |
| "invalid %s file in revision %s", ProjectConfig.PROJECT_CONFIG, r.getCommit().name())); | |
| r.assertMessage( | |
| String.format( | |
| "ERROR: commit %s: Parameter 'label.Foo.%s' is deprecated and cannot be set," | |
| + " use 'is:MIN' in 'label.Foo.copyCondition' instead.", | |
| abbreviateName(r.getCommit()), LabelConfigValidator.KEY_COPY_MIN_SCORE)); | |
| r.assertMessage( | |
| String.format( | |
| "ERROR: commit %s: Parameter 'label.Foo.%s' is deprecated and cannot be set," | |
| + " use 'is:MAX' in 'label.Foo.copyCondition' instead.", | |
| abbreviateName(r.getCommit()), LabelConfigValidator.KEY_COPY_MAX_SCORE)); | |
| } | |
| @Test | |
| public void setCopyCondition() throws Exception { | |
| fetchRefsMetaConfig(); | |
| PushOneCommit push = | |
| pushFactory.create( | |
| admin.newIdent(), | |
| testRepo, | |
| "Test Change", | |
| ProjectConfig.PROJECT_CONFIG, | |
| String.format("[label \"Foo\"]\n %s = is:ANY", ProjectConfig.KEY_COPY_CONDITION)); | |
| PushOneCommit.Result r = push.to(RefNames.REFS_CONFIG); | |
| r.assertOkStatus(); | |
| } | |
| @Test | |
| public void validateLabelConfigInInitialCommit() throws Exception { | |
| try (TestRepository<Repository> testRepo = | |
| new TestRepository<>(repoManager.openRepository(project))) { | |
| testRepo.delete(RefNames.REFS_CONFIG); | |
| } | |
| PushOneCommit push = | |
| pushFactory | |
| .create( | |
| admin.newIdent(), | |
| testRepo, | |
| "Test Change", | |
| ProjectConfig.PROJECT_CONFIG, | |
| INVALID_PRROJECT_CONFIG) | |
| .setParents(ImmutableList.of()); | |
| PushOneCommit.Result r = push.to(RefNames.REFS_CONFIG); | |
| r.assertErrorStatus( | |
| String.format( | |
| "invalid %s file in revision %s", ProjectConfig.PROJECT_CONFIG, r.getCommit().name())); | |
| } | |
| private void fetchRefsMetaConfig() throws Exception { | |
| fetch(testRepo, RefNames.REFS_CONFIG + ":" + RefNames.REFS_CONFIG); | |
| testRepo.reset(RefNames.REFS_CONFIG); | |
| } | |
| private String abbreviateName(AnyObjectId id) throws Exception { | |
| return ObjectIds.abbreviateName(id, testRepo.getRevWalk().getObjectReader()); | |
| } | |
| } |