| // Copyright (C) 2017 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.server.mail; | |
| import static com.google.common.truth.Truth.assertWithMessage; | |
| import static com.google.gerrit.acceptance.testsuite.project.TestProjectUpdate.allow; | |
| import static com.google.gerrit.acceptance.testsuite.project.TestProjectUpdate.allowLabel; | |
| import static com.google.gerrit.acceptance.testsuite.project.TestProjectUpdate.block; | |
| import static com.google.gerrit.entities.NotifyConfig.NotifyType.ABANDONED_CHANGES; | |
| import static com.google.gerrit.entities.NotifyConfig.NotifyType.ALL_COMMENTS; | |
| import static com.google.gerrit.entities.NotifyConfig.NotifyType.NEW_CHANGES; | |
| import static com.google.gerrit.entities.NotifyConfig.NotifyType.NEW_PATCHSETS; | |
| import static com.google.gerrit.entities.NotifyConfig.NotifyType.SUBMITTED_CHANGES; | |
| import static com.google.gerrit.extensions.api.changes.NotifyHandling.ALL; | |
| import static com.google.gerrit.extensions.api.changes.NotifyHandling.NONE; | |
| import static com.google.gerrit.extensions.api.changes.NotifyHandling.OWNER; | |
| import static com.google.gerrit.extensions.api.changes.NotifyHandling.OWNER_REVIEWERS; | |
| import static com.google.gerrit.extensions.client.GeneralPreferencesInfo.EmailStrategy.CC_ON_OWN_COMMENTS; | |
| import static com.google.gerrit.extensions.client.GeneralPreferencesInfo.EmailStrategy.ENABLED; | |
| import static com.google.gerrit.server.group.SystemGroupBackend.ANONYMOUS_USERS; | |
| import static com.google.gerrit.server.group.SystemGroupBackend.REGISTERED_USERS; | |
| import static com.google.gerrit.server.project.testing.TestLabels.labelBuilder; | |
| import static com.google.gerrit.server.project.testing.TestLabels.value; | |
| import com.google.common.collect.ImmutableList; | |
| import com.google.common.collect.ImmutableSet; | |
| import com.google.common.truth.Truth; | |
| import com.google.gerrit.acceptance.AbstractNotificationTest; | |
| import com.google.gerrit.acceptance.PushOneCommit; | |
| import com.google.gerrit.acceptance.TestAccount; | |
| import com.google.gerrit.acceptance.testsuite.project.ProjectOperations; | |
| import com.google.gerrit.acceptance.testsuite.request.RequestScopeOperations; | |
| import com.google.gerrit.common.Nullable; | |
| import com.google.gerrit.entities.Address; | |
| import com.google.gerrit.entities.LabelId; | |
| import com.google.gerrit.entities.LabelType; | |
| import com.google.gerrit.entities.NotifyConfig; | |
| import com.google.gerrit.entities.NotifyConfig.Header; | |
| import com.google.gerrit.entities.NotifyConfig.NotifyType; | |
| import com.google.gerrit.entities.Permission; | |
| import com.google.gerrit.entities.Project; | |
| import com.google.gerrit.extensions.api.changes.AbandonInput; | |
| import com.google.gerrit.extensions.api.changes.DeleteReviewerInput; | |
| import com.google.gerrit.extensions.api.changes.DeleteVoteInput; | |
| import com.google.gerrit.extensions.api.changes.NotifyHandling; | |
| import com.google.gerrit.extensions.api.changes.ReviewInput; | |
| import com.google.gerrit.extensions.api.changes.ReviewerInput; | |
| import com.google.gerrit.extensions.api.changes.SubmitInput; | |
| import com.google.gerrit.extensions.api.projects.ConfigInput; | |
| import com.google.gerrit.extensions.client.GeneralPreferencesInfo; | |
| import com.google.gerrit.extensions.client.GeneralPreferencesInfo.EmailStrategy; | |
| import com.google.gerrit.extensions.client.InheritableBoolean; | |
| import com.google.gerrit.extensions.client.ReviewerState; | |
| import com.google.gerrit.extensions.client.SubmitType; | |
| import com.google.gerrit.extensions.common.CommitInfo; | |
| import com.google.gerrit.extensions.common.CommitMessageInput; | |
| import com.google.gerrit.server.restapi.change.PostReviewOp; | |
| import com.google.inject.Inject; | |
| import java.util.UUID; | |
| import org.eclipse.jgit.junit.TestRepository; | |
| import org.eclipse.jgit.lib.Repository; | |
| import org.junit.Before; | |
| import org.junit.Test; | |
| public class ChangeNotificationsIT extends AbstractNotificationTest { | |
| @Inject private ProjectOperations projectOperations; | |
| @Inject private RequestScopeOperations requestScopeOperations; | |
| /* | |
| * Set up for extra standard test accounts and permissions. | |
| */ | |
| private TestAccount other; | |
| private TestAccount extraReviewer; | |
| private TestAccount extraCcer; | |
| @Before | |
| public void createExtraAccounts() throws Exception { | |
| extraReviewer = | |
| accountCreator.create("extraReviewer", "extraReviewer@example.com", "extraReviewer", null); | |
| extraCcer = accountCreator.create("extraCcer", "extraCcer@example.com", "extraCcer", null); | |
| other = accountCreator.create("other", "other@example.com", "other", null); | |
| } | |
| @Before | |
| public void grantPermissions() throws Exception { | |
| projectOperations | |
| .project(project) | |
| .forUpdate() | |
| .add(allow(Permission.FORGE_COMMITTER).ref("refs/*").group(REGISTERED_USERS)) | |
| .add(allow(Permission.SUBMIT).ref("refs/*").group(REGISTERED_USERS)) | |
| .add(allow(Permission.SUBMIT_AS).ref("refs/*").group(REGISTERED_USERS)) | |
| .add(allow(Permission.ABANDON).ref("refs/*").group(REGISTERED_USERS)) | |
| .add(allowLabel(LabelId.CODE_REVIEW).ref("refs/*").group(REGISTERED_USERS).range(-2, +2)) | |
| .update(); | |
| } | |
| /* | |
| * AbandonedSender tests. | |
| */ | |
| @Test | |
| public void abandonReviewableChangeByOwner() throws Exception { | |
| StagedChange sc = stageReviewableChange(); | |
| abandon(sc.changeId, sc.owner); | |
| assertThat(sender) | |
| .sent("abandon", sc) | |
| .cc(sc.reviewer, sc.ccer) | |
| .cc(StagedUsers.REVIEWER_BY_EMAIL, StagedUsers.CC_BY_EMAIL) | |
| .bcc(sc.starrer) | |
| .bcc(ABANDONED_CHANGES) | |
| .noOneElse(); | |
| assertThat(sender).didNotSend(); | |
| } | |
| @Test | |
| public void abandonReviewableChangeByOwnerCcingSelf() throws Exception { | |
| StagedChange sc = stageReviewableChange(); | |
| abandon(sc.changeId, sc.owner, CC_ON_OWN_COMMENTS); | |
| assertThat(sender) | |
| .sent("abandon", sc) | |
| .to(sc.owner) | |
| .cc(sc.reviewer, sc.ccer) | |
| .cc(StagedUsers.REVIEWER_BY_EMAIL, StagedUsers.CC_BY_EMAIL) | |
| .bcc(sc.starrer) | |
| .bcc(ABANDONED_CHANGES) | |
| .noOneElse(); | |
| assertThat(sender).didNotSend(); | |
| } | |
| @Test | |
| public void abandonReviewableChangeByOther() throws Exception { | |
| StagedChange sc = stageReviewableChange(); | |
| TestAccount other = accountCreator.create("other", "other@example.com", "other", null); | |
| abandon(sc.changeId, other); | |
| assertThat(sender) | |
| .sent("abandon", sc) | |
| .to(sc.owner) | |
| .cc(sc.reviewer, sc.ccer) | |
| .cc(StagedUsers.REVIEWER_BY_EMAIL, StagedUsers.CC_BY_EMAIL) | |
| .bcc(sc.starrer) | |
| .bcc(ABANDONED_CHANGES) | |
| .noOneElse(); | |
| assertThat(sender).didNotSend(); | |
| } | |
| @Test | |
| public void abandonReviewableChangeByOtherCcingSelf() throws Exception { | |
| StagedChange sc = stageReviewableChange(); | |
| TestAccount other = accountCreator.create("other", "other@example.com", "other", null); | |
| abandon(sc.changeId, other, CC_ON_OWN_COMMENTS); | |
| assertThat(sender) | |
| .sent("abandon", sc) | |
| .to(sc.owner) | |
| .cc(sc.reviewer, sc.ccer, other) | |
| .cc(StagedUsers.REVIEWER_BY_EMAIL, StagedUsers.CC_BY_EMAIL) | |
| .bcc(sc.starrer) | |
| .bcc(ABANDONED_CHANGES) | |
| .noOneElse(); | |
| assertThat(sender).didNotSend(); | |
| } | |
| @Test | |
| public void abandonReviewableChangeNotifyOwnersReviewers() throws Exception { | |
| StagedChange sc = stageReviewableChange(); | |
| abandon(sc.changeId, sc.owner, OWNER_REVIEWERS); | |
| assertThat(sender) | |
| .sent("abandon", sc) | |
| .cc(sc.reviewer, sc.ccer) | |
| .cc(StagedUsers.REVIEWER_BY_EMAIL, StagedUsers.CC_BY_EMAIL) | |
| .noOneElse(); | |
| assertThat(sender).didNotSend(); | |
| } | |
| @Test | |
| public void abandonReviewableChangeNotifyOwner() throws Exception { | |
| StagedChange sc = stageReviewableChange(); | |
| abandon(sc.changeId, sc.owner, OWNER); | |
| assertThat(sender).didNotSend(); | |
| } | |
| @Test | |
| public void abandonReviewableChangeNotifyOwnerCcingSelf() throws Exception { | |
| StagedChange sc = stageReviewableChange(); | |
| abandon(sc.changeId, sc.owner, CC_ON_OWN_COMMENTS, OWNER); | |
| // Self-CC applies *after* need for sending notification is determined. | |
| // Since there are no recipients before including the user taking action, | |
| // there should no notification sent. | |
| assertThat(sender).didNotSend(); | |
| } | |
| @Test | |
| public void abandonReviewableChangeByOtherCcingSelfNotifyOwner() throws Exception { | |
| StagedChange sc = stageReviewableChange(); | |
| TestAccount other = accountCreator.create("other", "other@example.com", "other", null); | |
| abandon(sc.changeId, other, CC_ON_OWN_COMMENTS, OWNER); | |
| assertThat(sender).sent("abandon", sc).to(sc.owner).cc(other).noOneElse(); | |
| assertThat(sender).didNotSend(); | |
| } | |
| @Test | |
| public void abandonReviewableChangeNotifyNone() throws Exception { | |
| StagedChange sc = stageReviewableChange(); | |
| abandon(sc.changeId, sc.owner, NONE); | |
| assertThat(sender).didNotSend(); | |
| } | |
| @Test | |
| public void abandonReviewableChangeNotifyNoneCcingSelf() throws Exception { | |
| StagedChange sc = stageReviewableChange(); | |
| abandon(sc.changeId, sc.owner, CC_ON_OWN_COMMENTS, NONE); | |
| assertThat(sender).didNotSend(); | |
| } | |
| @Test | |
| public void abandonReviewableWipChange() throws Exception { | |
| StagedChange sc = stageReviewableWipChange(); | |
| abandon(sc.changeId, sc.owner); | |
| assertThat(sender) | |
| .sent("abandon", sc) | |
| .cc(sc.reviewer, sc.ccer) | |
| .cc(StagedUsers.REVIEWER_BY_EMAIL, StagedUsers.CC_BY_EMAIL) | |
| .bcc(sc.starrer) | |
| .bcc(ABANDONED_CHANGES) | |
| .noOneElse(); | |
| assertThat(sender).didNotSend(); | |
| } | |
| @Test | |
| public void abandonWipChange() throws Exception { | |
| StagedChange sc = stageWipChange(); | |
| abandon(sc.changeId, sc.owner); | |
| assertThat(sender).didNotSend(); | |
| } | |
| @Test | |
| public void abandonWipChangeNotifyAll() throws Exception { | |
| StagedChange sc = stageWipChange(); | |
| abandon(sc.changeId, sc.owner, ALL); | |
| assertThat(sender) | |
| .sent("abandon", sc) | |
| .cc(sc.reviewer, sc.ccer) | |
| .cc(StagedUsers.REVIEWER_BY_EMAIL, StagedUsers.CC_BY_EMAIL) | |
| .bcc(sc.starrer) | |
| .bcc(ABANDONED_CHANGES) | |
| .noOneElse(); | |
| assertThat(sender).didNotSend(); | |
| } | |
| private void abandon(String changeId, TestAccount by) throws Exception { | |
| abandon(changeId, by, ENABLED); | |
| } | |
| private void abandon(String changeId, TestAccount by, EmailStrategy emailStrategy) | |
| throws Exception { | |
| abandon(changeId, by, emailStrategy, null); | |
| } | |
| private void abandon(String changeId, TestAccount by, @Nullable NotifyHandling notify) | |
| throws Exception { | |
| abandon(changeId, by, ENABLED, notify); | |
| } | |
| private void abandon( | |
| String changeId, TestAccount by, EmailStrategy emailStrategy, @Nullable NotifyHandling notify) | |
| throws Exception { | |
| setEmailStrategy(by, emailStrategy); | |
| requestScopeOperations.setApiUser(by.id()); | |
| AbandonInput in = new AbandonInput(); | |
| if (notify != null) { | |
| in.notify = notify; | |
| } | |
| gApi.changes().id(changeId).abandon(in); | |
| } | |
| /* | |
| * ModifyReviewerSender tests (only for additions). | |
| */ | |
| private void addReviewerToReviewableChange(Adder adder) throws Exception { | |
| StagedChange sc = stageReviewableChange(); | |
| TestAccount reviewer = accountCreator.create("added", "added@example.com", "added", null); | |
| addReviewer(adder, sc.changeId, sc.owner, reviewer.email()); | |
| // TODO(logan): Should CCs be included? | |
| assertThat(sender) | |
| .sent("newchange", sc) | |
| .to(reviewer) | |
| .cc(sc.reviewer) | |
| .cc(StagedUsers.REVIEWER_BY_EMAIL, StagedUsers.CC_BY_EMAIL) | |
| .noOneElse(); | |
| assertThat(sender).didNotSend(); | |
| } | |
| @Test | |
| public void addReviewerToReviewableChangeSingly() throws Exception { | |
| addReviewerToReviewableChange(singly()); | |
| } | |
| @Test | |
| public void addReviewerToReviewableChangeBatch() throws Exception { | |
| addReviewerToReviewableChange(batch()); | |
| } | |
| @Test | |
| public void addReviewerToChangeNoAnonymousUsersNotified() throws Exception { | |
| StagedChange sc = stageReviewableChange(); | |
| // Remove read permission for anonymous users. | |
| projectOperations | |
| .project(project) | |
| .forUpdate() | |
| .add(block(Permission.READ).ref("refs/*").group(ANONYMOUS_USERS)) | |
| .add(allow(Permission.READ).ref("refs/*").group(REGISTERED_USERS)) | |
| .update(); | |
| TestAccount reviewer = accountCreator.create("added", "added@example.com", "added", null); | |
| addReviewer(singly(), sc.changeId, sc.owner, reviewer.email()); | |
| // No BY_EMAIL cc's. | |
| assertThat(sender).sent("newchange", sc).to(reviewer).cc(sc.reviewer).noOneElse(); | |
| assertThat(sender).didNotSend(); | |
| } | |
| private void addReviewerToReviewableChangeByOwnerCcingSelf(Adder adder) throws Exception { | |
| StagedChange sc = stageReviewableChange(); | |
| TestAccount reviewer = accountCreator.create("added", "added@example.com", "added", null); | |
| addReviewer(adder, sc.changeId, sc.owner, reviewer.email(), CC_ON_OWN_COMMENTS, null); | |
| // TODO(logan): Should CCs be included? | |
| assertThat(sender) | |
| .sent("newchange", sc) | |
| .to(reviewer) | |
| .cc(sc.owner, sc.reviewer) | |
| .cc(StagedUsers.REVIEWER_BY_EMAIL, StagedUsers.CC_BY_EMAIL) | |
| .noOneElse(); | |
| assertThat(sender).didNotSend(); | |
| } | |
| @Test | |
| public void addReviewerToReviewableChangeByOwnerCcingSelfSingly() throws Exception { | |
| addReviewerToReviewableChangeByOwnerCcingSelf(singly()); | |
| } | |
| @Test | |
| public void addReviewerToReviewableChangeByOwnerCcingSelfBatch() throws Exception { | |
| addReviewerToReviewableChangeByOwnerCcingSelf(batch()); | |
| } | |
| private void addReviewerToReviewableChangeByOther(Adder adder) throws Exception { | |
| TestAccount other = accountCreator.create("other", "other@example.com", "other", null); | |
| StagedChange sc = stageReviewableChange(); | |
| TestAccount reviewer = accountCreator.create("added", "added@example.com", "added", null); | |
| addReviewer(adder, sc.changeId, other, reviewer.email()); | |
| // TODO(logan): Should CCs be included? | |
| assertThat(sender) | |
| .sent("newchange", sc) | |
| .to(reviewer) | |
| .cc(sc.owner, sc.reviewer) | |
| .cc(StagedUsers.REVIEWER_BY_EMAIL, StagedUsers.CC_BY_EMAIL) | |
| .noOneElse(); | |
| assertThat(sender).didNotSend(); | |
| } | |
| @Test | |
| public void addReviewerToReviewableChangeByOtherSingly() throws Exception { | |
| addReviewerToReviewableChangeByOther(singly()); | |
| } | |
| @Test | |
| public void addReviewerToReviewableChangeByOtherBatch() throws Exception { | |
| addReviewerToReviewableChangeByOther(batch()); | |
| } | |
| private void addReviewerToReviewableChangeByOtherCcingSelf(Adder adder) throws Exception { | |
| TestAccount other = accountCreator.create("other", "other@example.com", "other", null); | |
| StagedChange sc = stageReviewableChange(); | |
| TestAccount reviewer = accountCreator.create("added", "added@example.com", "added", null); | |
| addReviewer(adder, sc.changeId, other, reviewer.email(), CC_ON_OWN_COMMENTS, null); | |
| // TODO(logan): Should CCs be included? | |
| assertThat(sender) | |
| .sent("newchange", sc) | |
| .to(reviewer) | |
| .cc(sc.owner, sc.reviewer, other) | |
| .cc(StagedUsers.REVIEWER_BY_EMAIL, StagedUsers.CC_BY_EMAIL) | |
| .noOneElse(); | |
| assertThat(sender).didNotSend(); | |
| } | |
| @Test | |
| public void addReviewerToReviewableChangeByOtherCcingSelfSingly() throws Exception { | |
| addReviewerToReviewableChangeByOtherCcingSelf(singly()); | |
| } | |
| @Test | |
| public void addReviewerToReviewableChangeByOtherCcingSelfBatch() throws Exception { | |
| addReviewerToReviewableChangeByOtherCcingSelf(batch()); | |
| } | |
| private void addReviewerByEmailToReviewableChange(Adder adder) throws Exception { | |
| String email = "addedbyemail@example.com"; | |
| StagedChange sc = stageReviewableChange(); | |
| addReviewer(adder, sc.changeId, sc.owner, email); | |
| // TODO(logan): Should CCs be included? | |
| assertThat(sender) | |
| .sent("newchange", sc) | |
| .to(email) | |
| .cc(sc.reviewer) | |
| .cc(StagedUsers.REVIEWER_BY_EMAIL, StagedUsers.CC_BY_EMAIL) | |
| .noOneElse(); | |
| assertThat(sender).didNotSend(); | |
| } | |
| @Test | |
| public void addReviewerByEmailToReviewableChangeSingly() throws Exception { | |
| addReviewerByEmailToReviewableChange(singly()); | |
| } | |
| @Test | |
| public void addReviewerByEmailToReviewableChangeBatch() throws Exception { | |
| addReviewerByEmailToReviewableChange(batch()); | |
| } | |
| private void addReviewerToWipChange(Adder adder) throws Exception { | |
| StagedChange sc = stageWipChange(); | |
| TestAccount reviewer = accountCreator.create("added", "added@example.com", "added", null); | |
| addReviewer(adder, sc.changeId, sc.owner, reviewer.email()); | |
| assertThat(sender).didNotSend(); | |
| } | |
| @Test | |
| public void addReviewerToWipChangeSingly() throws Exception { | |
| addReviewerToWipChange(singly()); | |
| } | |
| @Test | |
| public void addReviewerToWipChangeBatch() throws Exception { | |
| addReviewerToWipChange(batch()); | |
| } | |
| @Test | |
| public void addReviewerToReviewableWipChangeSingly() throws Exception { | |
| StagedChange sc = stageReviewableWipChange(); | |
| TestAccount reviewer = accountCreator.create("added", "added@example.com", "added", null); | |
| addReviewer(singly(), sc.changeId, sc.owner, reviewer.email()); | |
| // TODO(dborowitz): In theory this should match the batch case, but we don't currently pass | |
| // enough info into ModifyReviewersEmail#emailReviewers to distinguish the reviewStarted case. | |
| // Complicating the emailReviewers arguments is not the answer; this needs to be rewritten. | |
| // Tolerate the difference for now. | |
| assertThat(sender).didNotSend(); | |
| } | |
| @Test | |
| public void addReviewerToReviewableWipChangeBatch() throws Exception { | |
| StagedChange sc = stageReviewableWipChange(); | |
| TestAccount reviewer = accountCreator.create("added", "added@example.com", "added", null); | |
| addReviewer(batch(), sc.changeId, sc.owner, reviewer.email()); | |
| // For a review-started WIP change, same as in the notify=ALL case. It's not especially | |
| // important to notify just because a reviewer is added, but we do want to notify in the other | |
| // case that hits this codepath: posting an actual review. | |
| assertThat(sender) | |
| .sent("newchange", sc) | |
| .to(reviewer) | |
| .cc(sc.reviewer) | |
| .cc(StagedUsers.REVIEWER_BY_EMAIL, StagedUsers.CC_BY_EMAIL) | |
| .noOneElse(); | |
| } | |
| private void addReviewerToWipChangeNotifyAll(Adder adder) throws Exception { | |
| StagedChange sc = stageWipChange(); | |
| TestAccount reviewer = accountCreator.create("added", "added@example.com", "added", null); | |
| addReviewer(adder, sc.changeId, sc.owner, reviewer.email(), NotifyHandling.ALL); | |
| // TODO(logan): Should CCs be included? | |
| assertThat(sender) | |
| .sent("newchange", sc) | |
| .to(reviewer) | |
| .cc(sc.reviewer) | |
| .cc(StagedUsers.REVIEWER_BY_EMAIL, StagedUsers.CC_BY_EMAIL) | |
| .noOneElse(); | |
| assertThat(sender).didNotSend(); | |
| } | |
| @Test | |
| public void addReviewerToWipChangeNotifyAllSingly() throws Exception { | |
| addReviewerToWipChangeNotifyAll(singly()); | |
| } | |
| @Test | |
| public void addReviewerToWipChangeNotifyAllBatch() throws Exception { | |
| addReviewerToWipChangeNotifyAll(batch()); | |
| } | |
| private void addReviewerToReviewableChangeNotifyOwnerReviewers(Adder adder) throws Exception { | |
| StagedChange sc = stageReviewableChange(); | |
| TestAccount reviewer = accountCreator.create("added", "added@example.com", "added", null); | |
| addReviewer(adder, sc.changeId, sc.owner, reviewer.email(), OWNER_REVIEWERS); | |
| // TODO(logan): Should CCs be included? | |
| assertThat(sender) | |
| .sent("newchange", sc) | |
| .to(reviewer) | |
| .cc(sc.reviewer) | |
| .cc(StagedUsers.REVIEWER_BY_EMAIL, StagedUsers.CC_BY_EMAIL) | |
| .noOneElse(); | |
| assertThat(sender).didNotSend(); | |
| } | |
| @Test | |
| public void addReviewerToReviewableChangeNotifyOwnerReviewersSingly() throws Exception { | |
| addReviewerToReviewableChangeNotifyOwnerReviewers(singly()); | |
| } | |
| @Test | |
| public void addReviewerToReviewableChangeNotifyOwnerReviewersBatch() throws Exception { | |
| addReviewerToReviewableChangeNotifyOwnerReviewers(batch()); | |
| } | |
| private void addReviewerToReviewableChangeByOwnerCcingSelfNotifyOwner(Adder adder) | |
| throws Exception { | |
| StagedChange sc = stageReviewableChange(); | |
| TestAccount reviewer = accountCreator.create("added", "added@example.com", "added", null); | |
| addReviewer(adder, sc.changeId, sc.owner, reviewer.email(), CC_ON_OWN_COMMENTS, OWNER); | |
| assertThat(sender).didNotSend(); | |
| } | |
| @Test | |
| public void addReviewerToReviewableChangeByOwnerCcingSelfNotifyOwnerSingly() throws Exception { | |
| addReviewerToReviewableChangeByOwnerCcingSelfNotifyOwner(singly()); | |
| } | |
| @Test | |
| public void addReviewerToReviewableChangeByOwnerCcingSelfNotifyOwnerBatch() throws Exception { | |
| addReviewerToReviewableChangeByOwnerCcingSelfNotifyOwner(batch()); | |
| } | |
| private void addReviewerToReviewableChangeByOwnerCcingSelfNotifyNone(Adder adder) | |
| throws Exception { | |
| StagedChange sc = stageReviewableChange(); | |
| TestAccount reviewer = accountCreator.create("added", "added@example.com", "added", null); | |
| addReviewer(adder, sc.changeId, sc.owner, reviewer.email(), CC_ON_OWN_COMMENTS, NONE); | |
| assertThat(sender).didNotSend(); | |
| } | |
| @Test | |
| public void addReviewerToReviewableChangeByOwnerCcingSelfNotifyNoneSingly() throws Exception { | |
| addReviewerToReviewableChangeByOwnerCcingSelfNotifyNone(singly()); | |
| } | |
| @Test | |
| public void addReviewerToReviewableChangeByOwnerCcingSelfNotifyNoneBatch() throws Exception { | |
| addReviewerToReviewableChangeByOwnerCcingSelfNotifyNone(batch()); | |
| } | |
| private void addNonUserReviewerByEmail(Adder adder) throws Exception { | |
| StagedChange sc = stageReviewableChange(); | |
| addReviewer(adder, sc.changeId, sc.owner, "nonexistent@example.com"); | |
| assertThat(sender) | |
| .sent("newchange", sc) | |
| .to("nonexistent@example.com") | |
| .cc(sc.reviewer) | |
| .cc(StagedUsers.CC_BY_EMAIL, StagedUsers.REVIEWER_BY_EMAIL) | |
| .noOneElse(); | |
| assertThat(sender).didNotSend(); | |
| } | |
| @Test | |
| public void addNonUserReviewerByEmailSingly() throws Exception { | |
| addNonUserReviewerByEmail(singly(ReviewerState.REVIEWER)); | |
| } | |
| @Test | |
| public void addNonUserReviewerByEmailBatch() throws Exception { | |
| addNonUserReviewerByEmail(batch(ReviewerState.REVIEWER)); | |
| } | |
| private void addNonUserCcByEmail(Adder adder) throws Exception { | |
| StagedChange sc = stageReviewableChange(); | |
| addReviewer(adder, sc.changeId, sc.owner, "nonexistent@example.com"); | |
| assertThat(sender) | |
| .sent("newchange", sc) | |
| .cc("nonexistent@example.com") | |
| .cc(sc.reviewer) | |
| .cc(StagedUsers.CC_BY_EMAIL, StagedUsers.REVIEWER_BY_EMAIL) | |
| .noOneElse(); | |
| assertThat(sender).didNotSend(); | |
| } | |
| @Test | |
| public void addNonUserCcByEmailSingly() throws Exception { | |
| addNonUserCcByEmail(singly(ReviewerState.CC)); | |
| } | |
| @Test | |
| public void addNonUserCcByEmailBatch() throws Exception { | |
| addNonUserCcByEmail(batch(ReviewerState.CC)); | |
| } | |
| private interface Adder { | |
| void addReviewer(String changeId, String reviewer, @Nullable NotifyHandling notify) | |
| throws Exception; | |
| } | |
| private Adder singly() { | |
| return singly(ReviewerState.REVIEWER); | |
| } | |
| private Adder singly(ReviewerState reviewerState) { | |
| return (String changeId, String reviewer, @Nullable NotifyHandling notify) -> { | |
| ReviewerInput in = new ReviewerInput(); | |
| in.reviewer = reviewer; | |
| in.state = reviewerState; | |
| if (notify != null) { | |
| in.notify = notify; | |
| } | |
| gApi.changes().id(changeId).addReviewer(in); | |
| }; | |
| } | |
| private Adder batch() { | |
| return batch(ReviewerState.REVIEWER); | |
| } | |
| private Adder batch(ReviewerState reviewerState) { | |
| return (String changeId, String reviewer, @Nullable NotifyHandling notify) -> { | |
| ReviewInput in = ReviewInput.noScore(); | |
| in.reviewer(reviewer, reviewerState, false); | |
| if (notify != null) { | |
| in.notify = notify; | |
| } | |
| gApi.changes().id(changeId).current().review(in); | |
| }; | |
| } | |
| private void addReviewer(Adder adder, String changeId, TestAccount by, String reviewer) | |
| throws Exception { | |
| addReviewer(adder, changeId, by, reviewer, ENABLED, null); | |
| } | |
| private void addReviewer( | |
| Adder adder, String changeId, TestAccount by, String reviewer, NotifyHandling notify) | |
| throws Exception { | |
| addReviewer(adder, changeId, by, reviewer, ENABLED, notify); | |
| } | |
| private void addReviewer( | |
| Adder adder, | |
| String changeId, | |
| TestAccount by, | |
| String reviewer, | |
| EmailStrategy emailStrategy, | |
| @Nullable NotifyHandling notify) | |
| throws Exception { | |
| setEmailStrategy(by, emailStrategy); | |
| requestScopeOperations.setApiUser(by.id()); | |
| adder.addReviewer(changeId, reviewer, notify); | |
| } | |
| /* | |
| * CommentSender tests. | |
| */ | |
| @Test | |
| public void commentOnReviewableChangeByOwner() throws Exception { | |
| StagedChange sc = stageReviewableChange(); | |
| review(sc.owner, sc.changeId, ENABLED); | |
| assertThat(sender) | |
| .sent("comment", sc) | |
| .cc(sc.reviewer, sc.ccer) | |
| .cc(StagedUsers.REVIEWER_BY_EMAIL, StagedUsers.CC_BY_EMAIL) | |
| .bcc(sc.starrer) | |
| .bcc(ALL_COMMENTS) | |
| .noOneElse(); | |
| assertThat(sender).didNotSend(); | |
| } | |
| @Test | |
| public void commentOnReviewableChangeByReviewer() throws Exception { | |
| StagedChange sc = stageReviewableChange(); | |
| review(sc.reviewer, sc.changeId, ENABLED); | |
| assertThat(sender) | |
| .sent("comment", sc) | |
| .to(sc.owner) | |
| .cc(sc.ccer) | |
| .cc(StagedUsers.REVIEWER_BY_EMAIL, StagedUsers.CC_BY_EMAIL) | |
| .bcc(sc.starrer) | |
| .bcc(ALL_COMMENTS) | |
| .noOneElse(); | |
| assertThat(sender).didNotSend(); | |
| } | |
| @Test | |
| public void commentOnChangeWithNotifyConfig() throws Exception { | |
| try (ProjectConfigUpdate u = updateProject(project)) { | |
| NotifyConfig nc = | |
| NotifyConfig.builder() | |
| .setName("observer") | |
| .setNotify(ImmutableSet.of(NotifyType.ALL)) | |
| .setHeader(Header.CC) | |
| .addAddress(Address.create("observer@example.com")) | |
| .build(); | |
| u.getConfig().putNotifyConfig("observer", nc); | |
| u.save(); | |
| } | |
| StagedChange sc = stageReviewableChange(); | |
| review(sc.reviewer, sc.changeId, ENABLED); | |
| assertThat(sender) | |
| .sent("comment", sc) | |
| .to(sc.owner) | |
| .cc(sc.ccer) | |
| .cc(StagedUsers.REVIEWER_BY_EMAIL, StagedUsers.CC_BY_EMAIL) | |
| .cc("observer@example.com") | |
| .bcc(sc.starrer) | |
| .bcc(ALL_COMMENTS) | |
| .noOneElse(); | |
| assertThat(sender).didNotSend(); | |
| } | |
| @Test | |
| public void commentOnChangeNotVisibleToAnonymousByReviewer() throws Exception { | |
| StagedChange sc = stageReviewableChange(); | |
| // Remove read permission for anonymous users. | |
| projectOperations | |
| .project(project) | |
| .forUpdate() | |
| .add(block(Permission.READ).ref("refs/*").group(ANONYMOUS_USERS)) | |
| .add(allow(Permission.READ).ref("refs/*").group(REGISTERED_USERS)) | |
| .update(); | |
| review(sc.reviewer, sc.changeId, ENABLED); | |
| // Not cc'ed to BY_EMAIL added addresses. | |
| assertThat(sender) | |
| .sent("comment", sc) | |
| .to(sc.owner) | |
| .cc(sc.ccer) | |
| .bcc(sc.starrer) | |
| .bcc(ALL_COMMENTS) | |
| .noOneElse(); | |
| assertThat(sender).didNotSend(); | |
| } | |
| @Test | |
| public void commentOnChangeNotVisibleToAnonymousByReviewerWithNotifyConfig() throws Exception { | |
| try (ProjectConfigUpdate u = updateProject(project)) { | |
| NotifyConfig nc = | |
| NotifyConfig.builder() | |
| .setName("observer") | |
| .setNotify(ImmutableSet.of(NotifyType.ALL)) | |
| .setHeader(Header.CC) | |
| .addAddress(Address.create("observer@example.com")) | |
| .build(); | |
| u.getConfig().putNotifyConfig("observer", nc); | |
| u.save(); | |
| } | |
| StagedChange sc = stageReviewableChange(); | |
| // Remove read permission for anonymous users. | |
| projectOperations | |
| .project(project) | |
| .forUpdate() | |
| .add(block(Permission.READ).ref("refs/*").group(ANONYMOUS_USERS)) | |
| .add(allow(Permission.READ).ref("refs/*").group(REGISTERED_USERS)) | |
| .update(); | |
| review(sc.reviewer, sc.changeId, ENABLED); | |
| // Not cc'ed to BY_EMAIL added addresses. | |
| assertThat(sender) | |
| .sent("comment", sc) | |
| .to(sc.owner) | |
| .cc(sc.ccer) | |
| .cc("observer@example.com") | |
| .bcc(sc.starrer) | |
| .bcc(ALL_COMMENTS) | |
| .noOneElse(); | |
| assertThat(sender).didNotSend(); | |
| } | |
| @Test | |
| public void commentOnReviewableChangeByOwnerCcingSelf() throws Exception { | |
| StagedChange sc = stageReviewableChange(); | |
| review(sc.owner, sc.changeId, CC_ON_OWN_COMMENTS); | |
| assertThat(sender) | |
| .sent("comment", sc) | |
| .to(sc.owner) | |
| .cc(sc.reviewer, sc.ccer) | |
| .cc(StagedUsers.REVIEWER_BY_EMAIL, StagedUsers.CC_BY_EMAIL) | |
| .bcc(sc.starrer) | |
| .bcc(ALL_COMMENTS) | |
| .noOneElse(); | |
| assertThat(sender).didNotSend(); | |
| } | |
| @Test | |
| public void commentOnReviewableChangeByReviewerCcingSelf() throws Exception { | |
| StagedChange sc = stageReviewableChange(); | |
| review(sc.reviewer, sc.changeId, CC_ON_OWN_COMMENTS); | |
| assertThat(sender) | |
| .sent("comment", sc) | |
| .to(sc.owner) | |
| .cc(sc.reviewer, sc.ccer) | |
| .cc(StagedUsers.REVIEWER_BY_EMAIL, StagedUsers.CC_BY_EMAIL) | |
| .bcc(sc.starrer) | |
| .bcc(ALL_COMMENTS) | |
| .noOneElse(); | |
| assertThat(sender).didNotSend(); | |
| } | |
| @Test | |
| public void commentOnReviewableChangeByOther() throws Exception { | |
| TestAccount other = accountCreator.create("other", "other@example.com", "other", null); | |
| StagedChange sc = stageReviewableChange(); | |
| review(other, sc.changeId, ENABLED); | |
| assertThat(sender) | |
| .sent("comment", sc) | |
| .to(sc.owner) | |
| .cc(sc.reviewer, sc.ccer) | |
| .cc(StagedUsers.REVIEWER_BY_EMAIL, StagedUsers.CC_BY_EMAIL) | |
| .bcc(sc.starrer) | |
| .bcc(ALL_COMMENTS) | |
| .noOneElse(); | |
| assertThat(sender).didNotSend(); | |
| } | |
| @Test | |
| public void commentOnReviewableChangeByOtherCcingSelf() throws Exception { | |
| TestAccount other = accountCreator.create("other", "other@example.com", "other", null); | |
| StagedChange sc = stageReviewableChange(); | |
| review(other, sc.changeId, CC_ON_OWN_COMMENTS); | |
| assertThat(sender) | |
| .sent("comment", sc) | |
| .to(sc.owner) | |
| .cc(sc.reviewer, sc.ccer, other) | |
| .cc(StagedUsers.REVIEWER_BY_EMAIL, StagedUsers.CC_BY_EMAIL) | |
| .bcc(sc.starrer) | |
| .bcc(ALL_COMMENTS) | |
| .noOneElse(); | |
| assertThat(sender).didNotSend(); | |
| } | |
| @Test | |
| public void commentOnReviewableChangeByOwnerNotifyOwnerReviewers() throws Exception { | |
| StagedChange sc = stageReviewableChange(); | |
| review(sc.owner, sc.changeId, ENABLED, OWNER_REVIEWERS); | |
| assertThat(sender) | |
| .sent("comment", sc) | |
| .cc(sc.reviewer, sc.ccer) | |
| .cc(StagedUsers.REVIEWER_BY_EMAIL, StagedUsers.CC_BY_EMAIL) | |
| .noOneElse(); | |
| assertThat(sender).didNotSend(); | |
| } | |
| @Test | |
| public void commentOnReviewableChangeByOwnerNotifyOwner() throws Exception { | |
| StagedChange sc = stageReviewableChange(); | |
| review(sc.owner, sc.changeId, ENABLED, OWNER); | |
| assertThat(sender).didNotSend(); | |
| } | |
| @Test | |
| public void commentOnReviewableChangeByOwnerCcingSelfNotifyOwner() throws Exception { | |
| StagedChange sc = stageReviewableChange(); | |
| setEmailStrategy(sc.owner, CC_ON_OWN_COMMENTS); | |
| review(sc.owner, sc.changeId, ENABLED, OWNER); | |
| assertThat(sender).didNotSend(); // TODO(logan): Why not send to owner? | |
| } | |
| @Test | |
| public void commentOnReviewableChangeByOwnerNotifyNone() throws Exception { | |
| StagedChange sc = stageReviewableChange(); | |
| review(sc.owner, sc.changeId, ENABLED, NONE); | |
| assertThat(sender).didNotSend(); | |
| } | |
| @Test | |
| public void commentOnReviewableChangeByOwnerCcingSelfNotifyNone() throws Exception { | |
| StagedChange sc = stageReviewableChange(); | |
| setEmailStrategy(sc.owner, CC_ON_OWN_COMMENTS); | |
| review(sc.owner, sc.changeId, ENABLED, NONE); | |
| assertThat(sender).didNotSend(); // TODO(logan): Why not send to owner? | |
| } | |
| @Test | |
| public void commentOnReviewableChangeByBot() throws Exception { | |
| StagedChange sc = stageReviewableChange(); | |
| TestAccount bot = sc.testAccount("bot"); | |
| review(bot, sc.changeId, ENABLED, null, "autogenerated:bot"); | |
| assertThat(sender) | |
| .sent("comment", sc) | |
| .to(sc.owner) | |
| .cc(sc.reviewer, sc.ccer) | |
| .cc(StagedUsers.REVIEWER_BY_EMAIL, StagedUsers.CC_BY_EMAIL) | |
| .noOneElse(); | |
| assertThat(sender).didNotSend(); | |
| } | |
| @Test | |
| public void commentOnWipChangeByOwner() throws Exception { | |
| StagedChange sc = stageWipChange(); | |
| review(sc.owner, sc.changeId, ENABLED); | |
| assertThat(sender).didNotSend(); | |
| } | |
| @Test | |
| public void commentOnWipChangeByOwnerCcingSelf() throws Exception { | |
| StagedChange sc = stageWipChange(); | |
| review(sc.owner, sc.changeId, CC_ON_OWN_COMMENTS); | |
| assertThat(sender).didNotSend(); | |
| } | |
| @Test | |
| public void commentOnWipChangeByOwnerNotifyAll() throws Exception { | |
| StagedChange sc = stageWipChange(); | |
| review(sc.owner, sc.changeId, ENABLED, ALL); | |
| assertThat(sender) | |
| .sent("comment", sc) | |
| .cc(sc.reviewer, sc.ccer) | |
| .cc(StagedUsers.REVIEWER_BY_EMAIL, StagedUsers.CC_BY_EMAIL) | |
| .bcc(sc.starrer) | |
| .bcc(ALL_COMMENTS) | |
| .noOneElse(); | |
| assertThat(sender).didNotSend(); | |
| } | |
| @Test | |
| public void commentOnWipChangeByBot() throws Exception { | |
| StagedChange sc = stageWipChange(); | |
| TestAccount bot = sc.testAccount("bot"); | |
| review(bot, sc.changeId, ENABLED, null, "autogenerated:tag"); | |
| assertThat(sender).sent("comment", sc).to(sc.owner).noOneElse(); | |
| assertThat(sender).didNotSend(); | |
| } | |
| @Test | |
| public void commentOnReviewableWipChangeByBot() throws Exception { | |
| StagedChange sc = stageReviewableWipChange(); | |
| TestAccount bot = sc.testAccount("bot"); | |
| review(bot, sc.changeId, ENABLED, null, "autogenerated:tag"); | |
| assertThat(sender).sent("comment", sc).to(sc.owner).noOneElse(); | |
| assertThat(sender).didNotSend(); | |
| } | |
| @Test | |
| public void commentOnReviewableWipChangeByBotNotifyAll() throws Exception { | |
| StagedChange sc = stageWipChange(); | |
| TestAccount bot = sc.testAccount("bot"); | |
| review(bot, sc.changeId, ENABLED, ALL, "tag"); | |
| assertThat(sender) | |
| .sent("comment", sc) | |
| .to(sc.owner) | |
| .cc(sc.reviewer, sc.ccer) | |
| .cc(StagedUsers.REVIEWER_BY_EMAIL, StagedUsers.CC_BY_EMAIL) | |
| .bcc(sc.starrer) | |
| .bcc(ALL_COMMENTS) | |
| .noOneElse(); | |
| assertThat(sender).didNotSend(); | |
| } | |
| @Test | |
| public void commentOnReviewableWipChangeByOwner() throws Exception { | |
| StagedChange sc = stageReviewableWipChange(); | |
| review(sc.owner, sc.changeId, ENABLED); | |
| assertThat(sender) | |
| .sent("comment", sc) | |
| .cc(sc.reviewer, sc.ccer) | |
| .cc(StagedUsers.REVIEWER_BY_EMAIL, StagedUsers.CC_BY_EMAIL) | |
| .bcc(sc.starrer) | |
| .bcc(ALL_COMMENTS) | |
| .noOneElse(); | |
| assertThat(sender).didNotSend(); | |
| } | |
| @Test | |
| public void noCommentAndSetWorkInProgress() throws Exception { | |
| StagedChange sc = stageReviewableChange(); | |
| ReviewInput in = ReviewInput.noScore().setWorkInProgress(true); | |
| gApi.changes().id(sc.changeId).current().review(in); | |
| assertThat(sender).didNotSend(); | |
| } | |
| @Test | |
| public void commentAndSetWorkInProgress() throws Exception { | |
| StagedChange sc = stageReviewableChange(); | |
| ReviewInput in = ReviewInput.noScore().message("ok").setWorkInProgress(true); | |
| gApi.changes().id(sc.changeId).current().review(in); | |
| assertThat(sender) | |
| .sent("comment", sc) | |
| .cc(sc.reviewer, sc.ccer) | |
| .cc(StagedUsers.REVIEWER_BY_EMAIL, StagedUsers.CC_BY_EMAIL) | |
| .bcc(sc.starrer) | |
| .bcc(ALL_COMMENTS) | |
| .noOneElse(); | |
| assertThat(sender).didNotSend(); | |
| } | |
| @Test | |
| public void commentOnWipChangeAndStartReview() throws Exception { | |
| StagedChange sc = stageWipChange(); | |
| ReviewInput in = ReviewInput.noScore().message("ok").setWorkInProgress(false); | |
| gApi.changes().id(sc.changeId).current().review(in); | |
| assertThat(sender) | |
| .sent("comment", sc) | |
| .cc(sc.reviewer, sc.ccer) | |
| .cc(StagedUsers.REVIEWER_BY_EMAIL, StagedUsers.CC_BY_EMAIL) | |
| .bcc(sc.starrer) | |
| .bcc(ALL_COMMENTS) | |
| .noOneElse(); | |
| assertThat(sender).didNotSend(); | |
| } | |
| @Test | |
| public void addReviewerOnWipChangeAndStartReview() throws Exception { | |
| StagedChange sc = stageWipChange(); | |
| ReviewInput in = ReviewInput.noScore().reviewer(other.email()).setWorkInProgress(false); | |
| gApi.changes().id(sc.changeId).current().review(in); | |
| assertThat(sender) | |
| .sent("comment", sc) | |
| .cc(sc.reviewer, sc.ccer, other) | |
| .cc(StagedUsers.REVIEWER_BY_EMAIL, StagedUsers.CC_BY_EMAIL) | |
| .bcc(sc.starrer) | |
| .bcc(ALL_COMMENTS) | |
| .noOneElse(); | |
| // TODO(logan): Should CCs be included? | |
| assertThat(sender) | |
| .sent("newchange", sc) | |
| .to(other) | |
| .cc(sc.reviewer) | |
| .cc(StagedUsers.REVIEWER_BY_EMAIL, StagedUsers.CC_BY_EMAIL) | |
| .noOneElse(); | |
| assertThat(sender).didNotSend(); | |
| } | |
| @Test | |
| public void startReviewMessageNotRepeated() throws Exception { | |
| // TODO(logan): Remove this test check once PolyGerrit workaround is rolled back. | |
| StagedChange sc = stageWipChange(); | |
| ReviewInput in = | |
| ReviewInput.noScore().message(PostReviewOp.START_REVIEW_MESSAGE).setWorkInProgress(false); | |
| gApi.changes().id(sc.changeId).current().review(in); | |
| Truth.assertThat(sender.getMessages()).isNotEmpty(); | |
| String body = sender.getMessages().get(0).body(); | |
| int idx = body.indexOf(PostReviewOp.START_REVIEW_MESSAGE); | |
| Truth.assertThat(idx).isAtLeast(0); | |
| Truth.assertThat(body.indexOf(PostReviewOp.START_REVIEW_MESSAGE, idx + 1)).isEqualTo(-1); | |
| } | |
| private void review(TestAccount account, String changeId, EmailStrategy strategy) | |
| throws Exception { | |
| review(account, changeId, strategy, null); | |
| } | |
| private void review( | |
| TestAccount account, String changeId, EmailStrategy strategy, @Nullable NotifyHandling notify) | |
| throws Exception { | |
| review(account, changeId, strategy, notify, null); | |
| } | |
| private void review( | |
| TestAccount account, | |
| String changeId, | |
| EmailStrategy strategy, | |
| @Nullable NotifyHandling notify, | |
| @Nullable String tag) | |
| throws Exception { | |
| setEmailStrategy(account, strategy); | |
| ReviewInput in = ReviewInput.recommend(); | |
| in.notify = notify; | |
| in.tag = tag; | |
| gApi.changes().id(changeId).current().review(in); | |
| } | |
| /* | |
| * CreateChangeSender tests. | |
| */ | |
| @Test | |
| public void createReviewableChange() throws Exception { | |
| StagedPreChange spc = stagePreChange("refs/for/master"); | |
| assertThat(sender) | |
| .sent("newchange", spc) | |
| .bcc(spc.watchingProjectOwner) | |
| .bcc(NEW_CHANGES, NEW_PATCHSETS) | |
| .noOneElse(); | |
| assertThat(sender).didNotSend(); | |
| } | |
| @Test | |
| public void verifyTitle() throws Exception { | |
| StagedPreChange spc = stagePreChange("refs/for/master"); | |
| assertThat(sender) | |
| .sent("newchange", spc) | |
| .title(String.format("[XS] Change in %s[master]: test commit", project)); | |
| assertThat(sender).didNotSend(); | |
| } | |
| @Test | |
| public void createWipChange() throws Exception { | |
| stagePreChange("refs/for/master%wip"); | |
| assertThat(sender).didNotSend(); | |
| } | |
| @Test | |
| public void createWipChangeWithWorkInProgressByDefaultForProject() throws Exception { | |
| setWorkInProgressByDefault(project, InheritableBoolean.TRUE); | |
| StagedPreChange spc = stagePreChange("refs/for/master"); | |
| Truth.assertThat(gApi.changes().id(spc.changeId).get().workInProgress).isTrue(); | |
| assertThat(sender).didNotSend(); | |
| } | |
| @Test | |
| public void createWipChangeWithWorkInProgressByDefaultForUser() throws Exception { | |
| // Make sure owner user is created | |
| StagedChange sc = stageReviewableChange(); | |
| // All was cleaned already | |
| assertThat(sender).didNotSend(); | |
| // Toggle workInProgress flag for owner | |
| GeneralPreferencesInfo prefs = gApi.accounts().id(sc.owner.id().get()).getPreferences(); | |
| prefs.workInProgressByDefault = true; | |
| gApi.accounts().id(sc.owner.id().get()).setPreferences(prefs); | |
| // Create another change without notification that should be wip | |
| StagedPreChange spc = stagePreChange("refs/for/master"); | |
| Truth.assertThat(gApi.changes().id(spc.changeId).get().workInProgress).isTrue(); | |
| assertThat(sender).didNotSend(); | |
| // Clean up workInProgressByDefault by owner | |
| prefs = gApi.accounts().id(sc.owner.id().get()).getPreferences(); | |
| Truth.assertThat(prefs.workInProgressByDefault).isTrue(); | |
| prefs.workInProgressByDefault = false; | |
| gApi.accounts().id(sc.owner.id().get()).setPreferences(prefs); | |
| } | |
| @Test | |
| public void createReviewableChangeWithNotifyOwnerReviewers() throws Exception { | |
| stagePreChange("refs/for/master%notify=OWNER_REVIEWERS"); | |
| assertThat(sender).didNotSend(); | |
| } | |
| @Test | |
| public void createReviewableChangeWithNotifyOwner() throws Exception { | |
| stagePreChange("refs/for/master%notify=OWNER"); | |
| assertThat(sender).didNotSend(); | |
| } | |
| @Test | |
| public void createReviewableChangeWithNotifyNone() throws Exception { | |
| stagePreChange("refs/for/master%notify=OWNER"); | |
| assertThat(sender).didNotSend(); | |
| } | |
| @Test | |
| public void createWipChangeWithNotifyAll() throws Exception { | |
| StagedPreChange spc = stagePreChange("refs/for/master%wip,notify=ALL"); | |
| assertThat(sender) | |
| .sent("newchange", spc) | |
| .bcc(spc.watchingProjectOwner) | |
| .bcc(NEW_CHANGES, NEW_PATCHSETS) | |
| .noOneElse(); | |
| assertThat(sender).didNotSend(); | |
| } | |
| @Test | |
| public void createReviewableChangeWithReviewersAndCcs() throws Exception { | |
| StagedPreChange spc = | |
| stagePreChange( | |
| "refs/for/master", | |
| users -> | |
| ImmutableList.of("r=" + users.reviewer.username(), "cc=" + users.ccer.username())); | |
| assertThat(sender) | |
| .sent("newchange", spc) | |
| .to(spc.reviewer) | |
| .cc(spc.ccer) | |
| .bcc(spc.watchingProjectOwner) | |
| .bcc(NEW_CHANGES, NEW_PATCHSETS) | |
| .noOneElse(); | |
| assertThat(sender).didNotSend(); | |
| } | |
| @Test | |
| public void createReviewableChangeWithReviewersAndCcsByEmail() throws Exception { | |
| StagedPreChange spc = | |
| stagePreChange( | |
| "refs/for/master", | |
| users -> ImmutableList.of("r=nobody1@example.com,cc=nobody2@example.com")); | |
| spc.supportReviewersByEmail = true; | |
| assertThat(sender) | |
| .sent("newchange", spc) | |
| .to("nobody1@example.com") | |
| .cc("nobody2@example.com") | |
| .bcc(spc.watchingProjectOwner) | |
| .bcc(NEW_CHANGES, NEW_PATCHSETS) | |
| .noOneElse(); | |
| assertThat(sender).didNotSend(); | |
| } | |
| /* | |
| * DeleteReviewerSender tests. | |
| */ | |
| @Test | |
| public void deleteReviewerFromReviewableChange() throws Exception { | |
| StagedChange sc = stageReviewableChangeWithExtraReviewer(); | |
| requestScopeOperations.setApiUser(sc.owner.id()); | |
| removeReviewer(sc, extraReviewer); | |
| assertThat(sender) | |
| .sent("deleteReviewer", sc) | |
| .to(extraReviewer) | |
| .cc(extraCcer, sc.reviewer, sc.ccer) | |
| .cc(StagedUsers.REVIEWER_BY_EMAIL, StagedUsers.CC_BY_EMAIL) | |
| .bcc(sc.starrer) | |
| .bcc(ALL_COMMENTS) | |
| .noOneElse(); | |
| assertThat(sender).didNotSend(); | |
| } | |
| @Test | |
| public void deleteReviewerFromReviewableChangeByOwnerCcingSelf() throws Exception { | |
| StagedChange sc = stageReviewableChangeWithExtraReviewer(); | |
| setEmailStrategy(sc.owner, EmailStrategy.CC_ON_OWN_COMMENTS); | |
| removeReviewer(sc, extraReviewer); | |
| assertThat(sender) | |
| .sent("deleteReviewer", sc) | |
| .to(sc.owner, extraReviewer) | |
| .cc(extraCcer, sc.reviewer, sc.ccer) | |
| .cc(StagedUsers.REVIEWER_BY_EMAIL, StagedUsers.CC_BY_EMAIL) | |
| .bcc(sc.starrer) | |
| .bcc(ALL_COMMENTS) | |
| .noOneElse(); | |
| assertThat(sender).didNotSend(); | |
| } | |
| @Test | |
| public void deleteReviewerFromReviewableChangeByAdmin() throws Exception { | |
| StagedChange sc = stageReviewableChangeWithExtraReviewer(); | |
| requestScopeOperations.setApiUser(admin.id()); | |
| removeReviewer(sc, extraReviewer); | |
| assertThat(sender) | |
| .sent("deleteReviewer", sc) | |
| .to(sc.owner, extraReviewer) | |
| .cc(extraCcer, sc.reviewer, sc.ccer) | |
| .cc(StagedUsers.REVIEWER_BY_EMAIL, StagedUsers.CC_BY_EMAIL) | |
| .bcc(sc.starrer) | |
| .bcc(ALL_COMMENTS) | |
| .noOneElse(); | |
| assertThat(sender).didNotSend(); | |
| } | |
| @Test | |
| public void deleteReviewerFromReviewableChangeByAdminCcingSelf() throws Exception { | |
| StagedChange sc = stageReviewableChangeWithExtraReviewer(); | |
| setEmailStrategy(admin, EmailStrategy.CC_ON_OWN_COMMENTS); | |
| requestScopeOperations.setApiUser(admin.id()); | |
| removeReviewer(sc, extraReviewer); | |
| assertThat(sender) | |
| .sent("deleteReviewer", sc) | |
| .to(sc.owner, extraReviewer) | |
| .cc(admin, extraCcer, sc.reviewer, sc.ccer) | |
| .cc(StagedUsers.REVIEWER_BY_EMAIL, StagedUsers.CC_BY_EMAIL) | |
| .bcc(sc.starrer) | |
| .bcc(ALL_COMMENTS) | |
| .noOneElse(); | |
| assertThat(sender).didNotSend(); | |
| } | |
| @Test | |
| public void deleteCcerFromReviewableChange() throws Exception { | |
| StagedChange sc = stageReviewableChangeWithExtraReviewer(); | |
| requestScopeOperations.setApiUser(sc.owner.id()); | |
| removeReviewer(sc, extraCcer); | |
| assertThat(sender) | |
| .sent("deleteReviewer", sc) | |
| .to(extraCcer) | |
| .cc(sc.reviewer, sc.ccer, extraReviewer) | |
| .cc(StagedUsers.REVIEWER_BY_EMAIL, StagedUsers.CC_BY_EMAIL) | |
| .bcc(sc.starrer) | |
| .bcc(ALL_COMMENTS) | |
| .noOneElse(); | |
| assertThat(sender).didNotSend(); | |
| } | |
| @Test | |
| public void deleteReviewerFromReviewableChangeNotifyOwnerReviewers() throws Exception { | |
| StagedChange sc = stageReviewableChangeWithExtraReviewer(); | |
| requestScopeOperations.setApiUser(sc.owner.id()); | |
| removeReviewer(sc, extraReviewer, NotifyHandling.OWNER_REVIEWERS); | |
| assertThat(sender) | |
| .sent("deleteReviewer", sc) | |
| .to(extraReviewer) | |
| .cc(extraCcer, sc.reviewer, sc.ccer) | |
| .cc(StagedUsers.REVIEWER_BY_EMAIL, StagedUsers.CC_BY_EMAIL) | |
| .noOneElse(); | |
| assertThat(sender).didNotSend(); | |
| } | |
| @Test | |
| public void deleteReviewerFromReviewableChangeNotifyOwner() throws Exception { | |
| StagedChange sc = stageReviewableChangeWithExtraReviewer(); | |
| removeReviewer(sc, extraReviewer, NotifyHandling.OWNER); | |
| assertThat(sender).didNotSend(); | |
| } | |
| @Test | |
| public void deleteReviewerFromReviewableChangeByOwnerCcingSelfNotifyOwner() throws Exception { | |
| StagedChange sc = stageReviewableChangeWithExtraReviewer(); | |
| setEmailStrategy(sc.owner, EmailStrategy.CC_ON_OWN_COMMENTS); | |
| removeReviewer(sc, extraReviewer, NotifyHandling.OWNER); | |
| assertThat(sender).sent("deleteReviewer", sc).to(sc.owner, extraReviewer).noOneElse(); | |
| assertThat(sender).didNotSend(); | |
| } | |
| @Test | |
| public void deleteReviewerFromReviewableChangeNotifyNone() throws Exception { | |
| StagedChange sc = stageReviewableChangeWithExtraReviewer(); | |
| removeReviewer(sc, extraReviewer, NotifyHandling.NONE); | |
| assertThat(sender).didNotSend(); | |
| } | |
| @Test | |
| public void deleteReviewerFromReviewableChangeByOwnerCcingSelfNotifyNone() throws Exception { | |
| StagedChange sc = stageReviewableChangeWithExtraReviewer(); | |
| setEmailStrategy(sc.owner, EmailStrategy.CC_ON_OWN_COMMENTS); | |
| removeReviewer(sc, extraReviewer, NotifyHandling.NONE); | |
| assertThat(sender).didNotSend(); | |
| } | |
| @Test | |
| public void deleteReviewerFromReviewableWipChange() throws Exception { | |
| StagedChange sc = stageReviewableWipChangeWithExtraReviewer(); | |
| removeReviewer(sc, extraReviewer); | |
| assertThat(sender).didNotSend(); | |
| } | |
| @Test | |
| public void deleteReviewerFromWipChange() throws Exception { | |
| StagedChange sc = stageWipChangeWithExtraReviewer(); | |
| removeReviewer(sc, extraReviewer); | |
| assertThat(sender).didNotSend(); | |
| } | |
| @Test | |
| public void deleteReviewerFromWipChangeNotifyAll() throws Exception { | |
| StagedChange sc = stageWipChangeWithExtraReviewer(); | |
| requestScopeOperations.setApiUser(sc.owner.id()); | |
| removeReviewer(sc, extraReviewer, NotifyHandling.ALL); | |
| assertThat(sender) | |
| .sent("deleteReviewer", sc) | |
| .to(extraReviewer) | |
| .cc(extraCcer, sc.reviewer, sc.ccer) | |
| .cc(StagedUsers.REVIEWER_BY_EMAIL, StagedUsers.CC_BY_EMAIL) | |
| .bcc(sc.starrer) | |
| .bcc(ALL_COMMENTS) | |
| .noOneElse(); | |
| assertThat(sender).didNotSend(); | |
| } | |
| @Test | |
| public void deleteReviewerWithApprovalFromWipChange() throws Exception { | |
| StagedChange sc = stageWipChangeWithExtraReviewer(); | |
| recommend(sc, extraReviewer); | |
| requestScopeOperations.setApiUser(sc.owner.id()); | |
| removeReviewer(sc, extraReviewer); | |
| assertThat(sender).sent("deleteReviewer", sc).to(extraReviewer).noOneElse(); | |
| assertThat(sender).didNotSend(); | |
| } | |
| @Test | |
| public void deleteReviewerWithApprovalFromWipChangeNotifyOwner() throws Exception { | |
| StagedChange sc = stageWipChangeWithExtraReviewer(); | |
| recommend(sc, extraReviewer); | |
| removeReviewer(sc, extraReviewer, NotifyHandling.OWNER); | |
| assertThat(sender).didNotSend(); | |
| } | |
| @Test | |
| public void deleteReviewerByEmailFromWipChange() throws Exception { | |
| StagedChange sc = stageWipChangeWithExtraReviewer(); | |
| gApi.changes().id(sc.changeId).reviewer(StagedUsers.REVIEWER_BY_EMAIL).remove(); | |
| assertThat(sender).didNotSend(); | |
| } | |
| private void recommend(StagedChange sc, TestAccount by) throws Exception { | |
| requestScopeOperations.setApiUser(by.id()); | |
| gApi.changes().id(sc.changeId).current().review(ReviewInput.recommend()); | |
| } | |
| private interface Stager { | |
| StagedChange stage() throws Exception; | |
| } | |
| private StagedChange stageChangeWithExtraReviewer(Stager stager) throws Exception { | |
| StagedChange sc = stager.stage(); | |
| ReviewInput in = | |
| ReviewInput.noScore() | |
| .reviewer(extraReviewer.email()) | |
| .reviewer(extraCcer.email(), ReviewerState.CC, false); | |
| requestScopeOperations.setApiUser(extraReviewer.id()); | |
| gApi.changes().id(sc.changeId).current().review(in); | |
| sender.clear(); | |
| return sc; | |
| } | |
| private StagedChange stageReviewableChangeWithExtraReviewer() throws Exception { | |
| StagedChange sc = stageChangeWithExtraReviewer(this::stageReviewableChange); | |
| sender.clear(); | |
| return sc; | |
| } | |
| private StagedChange stageReviewableWipChangeWithExtraReviewer() throws Exception { | |
| return stageChangeWithExtraReviewer(this::stageReviewableWipChange); | |
| } | |
| private StagedChange stageWipChangeWithExtraReviewer() throws Exception { | |
| StagedChange sc = stageChangeWithExtraReviewer(this::stageWipChange); | |
| assertThat(sender).didNotSend(); | |
| return sc; | |
| } | |
| private void removeReviewer(StagedChange sc, TestAccount account) throws Exception { | |
| sender.clear(); | |
| gApi.changes().id(sc.changeId).reviewer(account.email()).remove(); | |
| } | |
| private void removeReviewer(StagedChange sc, TestAccount account, NotifyHandling notify) | |
| throws Exception { | |
| sender.clear(); | |
| DeleteReviewerInput in = new DeleteReviewerInput(); | |
| in.notify = notify; | |
| gApi.changes().id(sc.changeId).reviewer(account.email()).remove(in); | |
| } | |
| /* | |
| * DeleteVoteSender tests. | |
| */ | |
| @Test | |
| public void deleteVoteFromReviewableChange() throws Exception { | |
| StagedChange sc = stageReviewableChangeWithExtraReviewer(); | |
| recommend(sc, extraReviewer); | |
| requestScopeOperations.setApiUser(sc.owner.id()); | |
| deleteVote(sc, extraReviewer); | |
| assertThat(sender) | |
| .sent("deleteVote", sc) | |
| .cc(sc.reviewer, sc.ccer, extraReviewer, extraCcer) | |
| .cc(StagedUsers.REVIEWER_BY_EMAIL, StagedUsers.CC_BY_EMAIL) | |
| .bcc(sc.starrer) | |
| .bcc(ALL_COMMENTS) | |
| .noOneElse(); | |
| assertThat(sender).didNotSend(); | |
| } | |
| @Test | |
| public void deleteVoteFromReviewableChangeWithSelfCc() throws Exception { | |
| StagedChange sc = stageReviewableChangeWithExtraReviewer(); | |
| recommend(sc, extraReviewer); | |
| setEmailStrategy(sc.owner, CC_ON_OWN_COMMENTS); | |
| requestScopeOperations.setApiUser(sc.owner.id()); | |
| deleteVote(sc, extraReviewer); | |
| assertThat(sender) | |
| .sent("deleteVote", sc) | |
| .to(sc.owner) | |
| .cc(sc.reviewer, sc.ccer, extraReviewer, extraCcer) | |
| .cc(StagedUsers.REVIEWER_BY_EMAIL, StagedUsers.CC_BY_EMAIL) | |
| .bcc(sc.starrer) | |
| .bcc(ALL_COMMENTS) | |
| .noOneElse(); | |
| assertThat(sender).didNotSend(); | |
| } | |
| @Test | |
| public void deleteVoteFromReviewableChangeByAdmin() throws Exception { | |
| StagedChange sc = stageReviewableChangeWithExtraReviewer(); | |
| recommend(sc, extraReviewer); | |
| requestScopeOperations.setApiUser(admin.id()); | |
| deleteVote(sc, extraReviewer); | |
| assertThat(sender) | |
| .sent("deleteVote", sc) | |
| .to(sc.owner) | |
| .cc(sc.reviewer, sc.ccer, extraReviewer, extraCcer) | |
| .cc(StagedUsers.REVIEWER_BY_EMAIL, StagedUsers.CC_BY_EMAIL) | |
| .bcc(sc.starrer) | |
| .bcc(ALL_COMMENTS) | |
| .noOneElse(); | |
| assertThat(sender).didNotSend(); | |
| } | |
| @Test | |
| public void deleteVoteFromReviewableChangeByAdminCcingSelf() throws Exception { | |
| StagedChange sc = stageReviewableChangeWithExtraReviewer(); | |
| recommend(sc, extraReviewer); | |
| setEmailStrategy(admin, EmailStrategy.CC_ON_OWN_COMMENTS); | |
| requestScopeOperations.setApiUser(admin.id()); | |
| deleteVote(sc, extraReviewer); | |
| assertThat(sender) | |
| .sent("deleteVote", sc) | |
| .to(sc.owner) | |
| .cc(sc.reviewer, sc.ccer, admin, extraReviewer, extraCcer) | |
| .cc(StagedUsers.REVIEWER_BY_EMAIL, StagedUsers.CC_BY_EMAIL) | |
| .bcc(sc.starrer) | |
| .bcc(ALL_COMMENTS) | |
| .noOneElse(); | |
| assertThat(sender).didNotSend(); | |
| } | |
| @Test | |
| public void deleteVoteFromReviewableChangeNotifyOwnerReviewers() throws Exception { | |
| StagedChange sc = stageReviewableChangeWithExtraReviewer(); | |
| recommend(sc, extraReviewer); | |
| requestScopeOperations.setApiUser(sc.owner.id()); | |
| deleteVote(sc, extraReviewer, NotifyHandling.OWNER_REVIEWERS); | |
| assertThat(sender) | |
| .sent("deleteVote", sc) | |
| .cc(sc.reviewer, sc.ccer, extraReviewer, extraCcer) | |
| .cc(StagedUsers.REVIEWER_BY_EMAIL, StagedUsers.CC_BY_EMAIL) | |
| .noOneElse(); | |
| assertThat(sender).didNotSend(); | |
| } | |
| @Test | |
| public void deleteVoteFromReviewableChangeNotifyOwnerReviewersWithSelfCc() throws Exception { | |
| StagedChange sc = stageReviewableChangeWithExtraReviewer(); | |
| recommend(sc, extraReviewer); | |
| setEmailStrategy(sc.owner, CC_ON_OWN_COMMENTS); | |
| requestScopeOperations.setApiUser(sc.owner.id()); | |
| deleteVote(sc, extraReviewer, NotifyHandling.OWNER_REVIEWERS); | |
| assertThat(sender) | |
| .sent("deleteVote", sc) | |
| .to(sc.owner) | |
| .cc(sc.reviewer, sc.ccer, extraReviewer, extraCcer) | |
| .cc(StagedUsers.REVIEWER_BY_EMAIL, StagedUsers.CC_BY_EMAIL) | |
| .noOneElse(); | |
| assertThat(sender).didNotSend(); | |
| } | |
| @Test | |
| public void deleteVoteFromReviewableChangeNotifyOwner() throws Exception { | |
| StagedChange sc = stageReviewableChangeWithExtraReviewer(); | |
| recommend(sc, extraReviewer); | |
| requestScopeOperations.setApiUser(admin.id()); | |
| deleteVote(sc, extraReviewer, NotifyHandling.OWNER); | |
| assertThat(sender).sent("deleteVote", sc).to(sc.owner).noOneElse(); | |
| assertThat(sender).didNotSend(); | |
| } | |
| @Test | |
| public void deleteVoteFromReviewableChangeNotifyNone() throws Exception { | |
| StagedChange sc = stageReviewableChangeWithExtraReviewer(); | |
| recommend(sc, extraReviewer); | |
| requestScopeOperations.setApiUser(sc.owner.id()); | |
| deleteVote(sc, extraReviewer, NotifyHandling.NONE); | |
| assertThat(sender).didNotSend(); | |
| } | |
| @Test | |
| public void deleteVoteFromReviewableChangeNotifyNoneWithSelfCc() throws Exception { | |
| StagedChange sc = stageReviewableChangeWithExtraReviewer(); | |
| recommend(sc, extraReviewer); | |
| setEmailStrategy(sc.owner, CC_ON_OWN_COMMENTS); | |
| requestScopeOperations.setApiUser(sc.owner.id()); | |
| deleteVote(sc, extraReviewer, NotifyHandling.NONE); | |
| assertThat(sender).didNotSend(); | |
| } | |
| @Test | |
| public void deleteVoteFromReviewableWipChange() throws Exception { | |
| StagedChange sc = stageReviewableWipChangeWithExtraReviewer(); | |
| recommend(sc, extraReviewer); | |
| requestScopeOperations.setApiUser(sc.owner.id()); | |
| deleteVote(sc, extraReviewer); | |
| assertThat(sender) | |
| .sent("deleteVote", sc) | |
| .cc(sc.reviewer, sc.ccer, extraReviewer, extraCcer) | |
| .cc(StagedUsers.REVIEWER_BY_EMAIL, StagedUsers.CC_BY_EMAIL) | |
| .bcc(sc.starrer) | |
| .bcc(ALL_COMMENTS) | |
| .noOneElse(); | |
| assertThat(sender).didNotSend(); | |
| } | |
| @Test | |
| public void deleteVoteFromWipChange() throws Exception { | |
| StagedChange sc = stageWipChangeWithExtraReviewer(); | |
| recommend(sc, extraReviewer); | |
| requestScopeOperations.setApiUser(sc.owner.id()); | |
| deleteVote(sc, extraReviewer); | |
| assertThat(sender) | |
| .sent("deleteVote", sc) | |
| .cc(sc.reviewer, sc.ccer, extraReviewer, extraCcer) | |
| .cc(StagedUsers.REVIEWER_BY_EMAIL, StagedUsers.CC_BY_EMAIL) | |
| .bcc(sc.starrer) | |
| .bcc(ALL_COMMENTS) | |
| .noOneElse(); | |
| assertThat(sender).didNotSend(); | |
| } | |
| private void deleteVote(StagedChange sc, TestAccount account) throws Exception { | |
| sender.clear(); | |
| gApi.changes().id(sc.changeId).reviewer(account.email()).deleteVote(LabelId.CODE_REVIEW); | |
| } | |
| private void deleteVote(StagedChange sc, TestAccount account, NotifyHandling notify) | |
| throws Exception { | |
| sender.clear(); | |
| DeleteVoteInput in = new DeleteVoteInput(); | |
| in.label = LabelId.CODE_REVIEW; | |
| in.notify = notify; | |
| gApi.changes().id(sc.changeId).reviewer(account.email()).deleteVote(in); | |
| } | |
| /* | |
| * MergedSender tests. | |
| */ | |
| @Test | |
| public void mergeByOwnerAllSubmitStrategies() throws Exception { | |
| mergeByOwnerAllSubmitStrategies(false); | |
| } | |
| @Test | |
| public void mergeByOwnerAllSubmitStrategiesWithAdvancingBranch() throws Exception { | |
| mergeByOwnerAllSubmitStrategies(true); | |
| } | |
| private void mergeByOwnerAllSubmitStrategies(boolean advanceBranchBeforeSubmitting) | |
| throws Exception { | |
| for (SubmitType submitType : SubmitType.values()) { | |
| try (ProjectConfigUpdate u = updateProject(project)) { | |
| u.getConfig().updateProject(p -> p.setSubmitType(submitType)); | |
| u.save(); | |
| } | |
| StagedChange sc = stageChangeReadyForMerge(); | |
| String name = submitType + " sender"; | |
| if (advanceBranchBeforeSubmitting) { | |
| if (submitType == SubmitType.FAST_FORWARD_ONLY) { | |
| continue; | |
| } | |
| try (Repository repo = repoManager.openRepository(project); | |
| TestRepository<Repository> tr = new TestRepository<>(repo)) { | |
| tr.branch("master").commit().create(); | |
| } | |
| name += " after branch has advanced"; | |
| } | |
| merge(sc.changeId, sc.owner); | |
| assertWithMessage(name) | |
| .about(fakeEmailSenders()) | |
| .that(sender) | |
| .sent("merged", sc) | |
| .cc(sc.reviewer, sc.ccer) | |
| .cc(StagedUsers.REVIEWER_BY_EMAIL, StagedUsers.CC_BY_EMAIL) | |
| .bcc(sc.starrer) | |
| .bcc(ALL_COMMENTS, SUBMITTED_CHANGES) | |
| .noOneElse(); | |
| assertWithMessage(name).about(fakeEmailSenders()).that(sender).didNotSend(); | |
| } | |
| } | |
| @Test | |
| public void mergeByOwnerCcingSelf() throws Exception { | |
| StagedChange sc = stageChangeReadyForMerge(); | |
| merge(sc.changeId, sc.owner, EmailStrategy.CC_ON_OWN_COMMENTS); | |
| assertThat(sender) | |
| .sent("merged", sc) | |
| .to(sc.owner) | |
| .cc(sc.reviewer, sc.ccer) | |
| .cc(StagedUsers.REVIEWER_BY_EMAIL, StagedUsers.CC_BY_EMAIL) | |
| .bcc(sc.starrer) | |
| .bcc(ALL_COMMENTS, SUBMITTED_CHANGES) | |
| .noOneElse(); | |
| assertThat(sender).didNotSend(); | |
| } | |
| @Test | |
| public void mergeByReviewer() throws Exception { | |
| StagedChange sc = stageChangeReadyForMerge(); | |
| merge(sc.changeId, sc.reviewer); | |
| assertThat(sender) | |
| .sent("merged", sc) | |
| .to(sc.owner) | |
| .cc(sc.ccer) | |
| .cc(StagedUsers.REVIEWER_BY_EMAIL, StagedUsers.CC_BY_EMAIL) | |
| .bcc(sc.starrer) | |
| .bcc(ALL_COMMENTS, SUBMITTED_CHANGES) | |
| .noOneElse(); | |
| assertThat(sender).didNotSend(); | |
| } | |
| @Test | |
| public void mergeByReviewerCcingSelf() throws Exception { | |
| StagedChange sc = stageChangeReadyForMerge(); | |
| merge(sc.changeId, sc.reviewer, EmailStrategy.CC_ON_OWN_COMMENTS); | |
| assertThat(sender) | |
| .sent("merged", sc) | |
| .to(sc.owner) | |
| .cc(sc.reviewer, sc.ccer) | |
| .cc(StagedUsers.REVIEWER_BY_EMAIL, StagedUsers.CC_BY_EMAIL) | |
| .bcc(sc.starrer) | |
| .bcc(ALL_COMMENTS, SUBMITTED_CHANGES) | |
| .noOneElse(); | |
| assertThat(sender).didNotSend(); | |
| } | |
| @Test | |
| public void mergeByOtherNotifyOwnerReviewers() throws Exception { | |
| StagedChange sc = stageChangeReadyForMerge(); | |
| merge(sc.changeId, other, OWNER_REVIEWERS); | |
| assertThat(sender) | |
| .sent("merged", sc) | |
| .to(sc.owner) | |
| .cc(sc.reviewer, sc.ccer) | |
| .cc(StagedUsers.REVIEWER_BY_EMAIL, StagedUsers.CC_BY_EMAIL) | |
| .noOneElse(); | |
| assertThat(sender).didNotSend(); | |
| } | |
| @Test | |
| public void mergeByOtherNotifyOwner() throws Exception { | |
| StagedChange sc = stageChangeReadyForMerge(); | |
| merge(sc.changeId, other, OWNER); | |
| assertThat(sender).sent("merged", sc).to(sc.owner).noOneElse(); | |
| assertThat(sender).didNotSend(); | |
| } | |
| @Test | |
| public void mergeByOtherCcingSelfNotifyOwner() throws Exception { | |
| StagedChange sc = stageChangeReadyForMerge(); | |
| setEmailStrategy(other, EmailStrategy.CC_ON_OWN_COMMENTS); | |
| merge(sc.changeId, other, OWNER); | |
| assertThat(sender).sent("merged", sc).to(sc.owner).noOneElse(); | |
| assertThat(sender).didNotSend(); | |
| } | |
| @Test | |
| public void mergeByOtherNotifyNone() throws Exception { | |
| StagedChange sc = stageChangeReadyForMerge(); | |
| merge(sc.changeId, other, NONE); | |
| assertThat(sender).didNotSend(); | |
| } | |
| @Test | |
| public void mergeByOtherCcingSelfNotifyNone() throws Exception { | |
| StagedChange sc = stageChangeReadyForMerge(); | |
| setEmailStrategy(other, EmailStrategy.CC_ON_OWN_COMMENTS); | |
| merge(sc.changeId, other, NONE); | |
| assertThat(sender).didNotSend(); | |
| } | |
| @Test | |
| public void mergeOnBehalfOfEmailEnabled_impersonatedOwnerNotified() throws Exception { | |
| StagedChange sc = stageChangeReadyForMerge(); | |
| // If notification is enabled, onBehalfOfUser is always notified. | |
| setEmailStrategy(sc.owner, ENABLED); | |
| merge(sc.changeId, other, sc.owner, ALL); | |
| assertThat(sender) | |
| .sent("merged", sc) | |
| .to(sc.owner) | |
| .cc(sc.reviewer, sc.ccer) | |
| .cc(StagedUsers.REVIEWER_BY_EMAIL, StagedUsers.CC_BY_EMAIL) | |
| .bcc(sc.starrer) | |
| .bcc(ALL_COMMENTS, SUBMITTED_CHANGES) | |
| .noOneElse(); | |
| assertThat(sender).didNotSend(); | |
| } | |
| @Test | |
| public void mergeOnBehalfOfEmailEnabled_impersonatedReviewerNotified() throws Exception { | |
| StagedChange sc = stageChangeReadyForMerge(); | |
| // If notification is enabled, onBehalfOfUser is always notified. | |
| setEmailStrategy(sc.reviewer, ENABLED); | |
| merge(sc.changeId, other, sc.reviewer, ALL); | |
| assertThat(sender) | |
| .sent("merged", sc) | |
| .to(sc.owner) | |
| .cc(sc.reviewer, sc.ccer) | |
| .cc(StagedUsers.REVIEWER_BY_EMAIL, StagedUsers.CC_BY_EMAIL) | |
| .bcc(sc.starrer) | |
| .bcc(ALL_COMMENTS, SUBMITTED_CHANGES) | |
| .noOneElse(); | |
| assertThat(sender).didNotSend(); | |
| } | |
| @Test | |
| public void mergeOnBehalfOfReviewerNotifyOwner_impersonatedReviewerInCC() throws Exception { | |
| StagedChange sc = stageChangeReadyForMerge(); | |
| setEmailStrategy(sc.reviewer, ENABLED); | |
| // Even though Submit strategy is OWNER, impersonated reviewer is added to CC. | |
| merge(sc.changeId, other, sc.reviewer, OWNER); | |
| assertThat(sender).sent("merged", sc).to(sc.owner).cc(sc.reviewer).noOneElse(); | |
| assertThat(sender).didNotSend(); | |
| } | |
| @Test | |
| public void mergeOnBehalfOfOtherNotifyOwner_impersonatedOtherInCC() throws Exception { | |
| StagedChange sc = stageChangeReadyForMerge(); | |
| // Unrelated impersonated user is added to CC. | |
| merge(sc.changeId, sc.reviewer, other, OWNER); | |
| assertThat(sender).sent("merged", sc).to(sc.owner).cc(other).noOneElse(); | |
| assertThat(sender).didNotSend(); | |
| } | |
| @Test | |
| public void mergeOnBehalfOfEmailDisabled_doesNotNotify() throws Exception { | |
| StagedChange sc = stageChangeReadyForMerge(); | |
| setEmailStrategy(other, EmailStrategy.DISABLED); | |
| merge(sc.changeId, sc.reviewer, other, OWNER); | |
| assertThat(sender).sent("merged", sc).to(sc.owner).noOneElse(); | |
| assertThat(sender).didNotSend(); | |
| } | |
| @Test | |
| public void mergeOnBehalfOfNotifyNone() throws Exception { | |
| StagedChange sc = stageChangeReadyForMerge(); | |
| merge(sc.changeId, other, sc.owner, NONE); | |
| assertThat(sender).didNotSend(); | |
| } | |
| @Test | |
| public void mergeByOtherAlwaysNotifiesAllIfThereIsAStickyApprovalDiff() throws Exception { | |
| StagedChange sc = stageChangeReadyForMergeWithStickyApprovalDiff(); | |
| // The user requests to notify NONE, but if there is a sticky approval diff we notify ALL. | |
| merge(sc.changeId, other, NONE); | |
| assertThat(sender) | |
| .sent("merged", sc) | |
| .to(sc.owner) | |
| .cc(sc.reviewer) | |
| .cc(sc.ccer) | |
| .cc(StagedUsers.REVIEWER_BY_EMAIL, StagedUsers.CC_BY_EMAIL) | |
| .bcc(sc.starrer) | |
| .bcc(SUBMITTED_CHANGES) | |
| .bcc(ALL_COMMENTS) | |
| .noOneElse(); | |
| assertThat(sender).didNotSend(); | |
| } | |
| @Test | |
| public void mergeOnBehalfOfAlwaysNotifiesAllIfThereIsAStickyApprovalDiff() throws Exception { | |
| StagedChange sc = stageChangeReadyForMergeWithStickyApprovalDiff(); | |
| // The user requests to notify NONE, but if there is a sticky approval diff we notify ALL. | |
| merge(sc.changeId, other, sc.owner, NONE); | |
| assertThat(sender) | |
| .sent("merged", sc) | |
| .to(sc.owner) | |
| .cc(sc.reviewer) | |
| .cc(sc.ccer) | |
| .cc(StagedUsers.REVIEWER_BY_EMAIL, StagedUsers.CC_BY_EMAIL) | |
| .bcc(sc.starrer) | |
| .bcc(SUBMITTED_CHANGES) | |
| .bcc(ALL_COMMENTS) | |
| .noOneElse(); | |
| assertThat(sender).didNotSend(); | |
| } | |
| private void merge(String changeId, TestAccount by) throws Exception { | |
| merge(changeId, by, ENABLED); | |
| } | |
| private void merge(String changeId, TestAccount by, EmailStrategy emailStrategy) | |
| throws Exception { | |
| setEmailStrategy(by, emailStrategy); | |
| requestScopeOperations.setApiUser(by.id()); | |
| gApi.changes().id(changeId).current().submit(); | |
| } | |
| private void merge(String changeId, TestAccount by, NotifyHandling notify) throws Exception { | |
| merge(changeId, by, ENABLED, notify); | |
| } | |
| private void merge( | |
| String changeId, TestAccount by, EmailStrategy emailStrategy, NotifyHandling notify) | |
| throws Exception { | |
| setEmailStrategy(by, emailStrategy); | |
| requestScopeOperations.setApiUser(by.id()); | |
| SubmitInput in = new SubmitInput(); | |
| in.notify = notify; | |
| gApi.changes().id(changeId).current().submit(in); | |
| } | |
| private void merge( | |
| String changeId, TestAccount by, TestAccount onBehalfOf, @Nullable NotifyHandling notify) | |
| throws Exception { | |
| requestScopeOperations.setApiUser(by.id()); | |
| SubmitInput in = new SubmitInput(); | |
| in.notify = notify; | |
| in.onBehalfOf = onBehalfOf.id().toString(); | |
| gApi.changes().id(changeId).current().submit(in); | |
| } | |
| private StagedChange stageChangeReadyForMerge() throws Exception { | |
| StagedChange sc = stageReviewableChange(); | |
| requestScopeOperations.setApiUser(sc.reviewer.id()); | |
| gApi.changes().id(sc.changeId).current().review(ReviewInput.approve()); | |
| sender.clear(); | |
| return sc; | |
| } | |
| private StagedChange stageChangeReadyForMergeWithStickyApprovalDiff() throws Exception { | |
| try (ProjectConfigUpdate u = updateProject(project)) { | |
| LabelType.Builder codeReview = | |
| labelBuilder( | |
| LabelId.CODE_REVIEW, | |
| value(2, "Looks good to me, approved"), | |
| value(1, "Looks good to me, but someone else must approve"), | |
| value(0, "No score"), | |
| value(-1, "I would prefer this is not submitted as is"), | |
| value(-2, "This shall not be submitted")) | |
| .setCopyCondition("is:ANY"); | |
| u.getConfig().upsertLabelType(codeReview.build()); | |
| u.save(); | |
| } | |
| StagedChange sc = stageReviewableChange(); | |
| requestScopeOperations.setApiUser(sc.reviewer.id()); | |
| gApi.changes().id(sc.changeId).current().review(ReviewInput.approve()); | |
| amendChange(sc.changeId, "refs/for/master", sc.owner, sc.repo).assertOkStatus(); | |
| sender.clear(); | |
| return sc; | |
| } | |
| /* | |
| * ReplacePatchSetSender tests. | |
| */ | |
| @Test | |
| public void newPatchSetByOwnerOnReviewableChange() throws Exception { | |
| StagedChange sc = stageReviewableChange(); | |
| pushTo(sc, "refs/for/master", sc.owner); | |
| assertThat(sender) | |
| .sent("newpatchset", sc) | |
| .to(sc.reviewer) | |
| .cc(sc.ccer) | |
| .cc(StagedUsers.REVIEWER_BY_EMAIL, StagedUsers.CC_BY_EMAIL) | |
| .bcc(sc.starrer) | |
| .bcc(NEW_PATCHSETS) | |
| .noOneElse(); | |
| assertThat(sender).didNotSend(); | |
| } | |
| @Test | |
| public void newPatchSetByOtherOnReviewableChange() throws Exception { | |
| StagedChange sc = stageReviewableChange(); | |
| pushTo(sc, "refs/for/master", other); | |
| assertThat(sender) | |
| .sent("newpatchset", sc) | |
| .notTo(sc.owner) // TODO(logan): This shouldn't be sent *from* the owner. | |
| .to(sc.reviewer, other) | |
| .cc(sc.ccer) | |
| .cc(StagedUsers.REVIEWER_BY_EMAIL, StagedUsers.CC_BY_EMAIL) | |
| .bcc(sc.starrer) | |
| .bcc(NEW_PATCHSETS) | |
| .noOneElse(); | |
| assertThat(sender).didNotSend(); | |
| } | |
| @Test | |
| public void newPatchSetByOtherOnReviewableChangeOwnerSelfCc() throws Exception { | |
| StagedChange sc = stageReviewableChange(); | |
| pushTo(sc, "refs/for/master", other, EmailStrategy.CC_ON_OWN_COMMENTS); | |
| assertThat(sender) | |
| .sent("newpatchset", sc) | |
| .notTo(sc.owner) // TODO(logan): This shouldn't be sent *from* the owner. | |
| .to(sc.reviewer, other) | |
| .cc(sc.ccer) | |
| .cc(StagedUsers.REVIEWER_BY_EMAIL, StagedUsers.CC_BY_EMAIL) | |
| .bcc(sc.starrer) | |
| .bcc(NEW_PATCHSETS) | |
| .noOneElse(); | |
| assertThat(sender).didNotSend(); | |
| } | |
| @Test | |
| public void newPatchSetByOtherOnReviewableChangeNotifyOwnerReviewers() throws Exception { | |
| StagedChange sc = stageReviewableChange(); | |
| pushTo(sc, "refs/for/master%notify=OWNER_REVIEWERS", other); | |
| assertThat(sender) | |
| .sent("newpatchset", sc) | |
| .notTo(sc.owner) // TODO(logan): This shouldn't be sent *from* the owner. | |
| .to(sc.reviewer) | |
| .cc(other) | |
| .cc(sc.ccer) | |
| .cc(StagedUsers.REVIEWER_BY_EMAIL, StagedUsers.CC_BY_EMAIL) | |
| .noOneElse(); | |
| assertThat(sender).didNotSend(); | |
| } | |
| @Test | |
| public void newPatchSetByOtherOnReviewableChangeOwnerSelfCcNotifyOwnerReviewers() | |
| throws Exception { | |
| StagedChange sc = stageReviewableChange(); | |
| pushTo(sc, "refs/for/master%notify=OWNER_REVIEWERS", other, EmailStrategy.CC_ON_OWN_COMMENTS); | |
| assertThat(sender) | |
| .sent("newpatchset", sc) | |
| .notTo(sc.owner) // TODO(logan): This shouldn't be sent *from* the owner. | |
| .to(sc.reviewer) | |
| .cc(other) | |
| .cc(sc.ccer) | |
| .cc(StagedUsers.REVIEWER_BY_EMAIL, StagedUsers.CC_BY_EMAIL) | |
| .noOneElse(); | |
| assertThat(sender).didNotSend(); | |
| } | |
| @Test | |
| public void newPatchSetByOtherOnReviewableChangeNotifyOwner() throws Exception { | |
| StagedChange sc = stageReviewableChange(); | |
| pushTo(sc, "refs/for/master%notify=OWNER", other); | |
| assertThat(sender).didNotSend(); | |
| } | |
| @Test | |
| public void newPatchSetByOtherOnReviewableChangeOwnerSelfCcNotifyOwner() throws Exception { | |
| StagedChange sc = stageReviewableChange(); | |
| pushTo(sc, "refs/for/master%notify=OWNER", other, EmailStrategy.CC_ON_OWN_COMMENTS); | |
| // TODO(logan): This email shouldn't come from the owner, and that's why | |
| // no email is currently sent (owner isn't CCing self). | |
| assertThat(sender).didNotSend(); | |
| } | |
| @Test | |
| public void newPatchSetByOtherOnReviewableChangeNotifyNone() throws Exception { | |
| StagedChange sc = stageReviewableChange(); | |
| pushTo(sc, "refs/for/master%notify=NONE", other); | |
| // TODO(logan): This email shouldn't come from the owner, and that's why | |
| // no email is currently sent (owner isn't CCing self). | |
| assertThat(sender).didNotSend(); | |
| } | |
| @Test | |
| public void newPatchSetByOtherOnReviewableChangeOwnerSelfCcNotifyNone() throws Exception { | |
| StagedChange sc = stageReviewableChange(); | |
| pushTo(sc, "refs/for/master%notify=NONE", other, EmailStrategy.CC_ON_OWN_COMMENTS); | |
| assertThat(sender).didNotSend(); | |
| } | |
| @Test | |
| public void newPatchSetByOwnerOnReviewableChangeToWip() throws Exception { | |
| StagedChange sc = stageReviewableChange(); | |
| pushTo(sc, "refs/for/master%wip", sc.owner); | |
| assertThat(sender).didNotSend(); | |
| } | |
| @Test | |
| public void newPatchSetOnWipChange() throws Exception { | |
| StagedChange sc = stageWipChange(); | |
| pushTo(sc, "refs/for/master%wip", sc.owner); | |
| assertThat(sender).didNotSend(); | |
| } | |
| @Test | |
| public void newPatchSetOnWipChangeNotifyAll() throws Exception { | |
| StagedChange sc = stageWipChange(); | |
| pushTo(sc, "refs/for/master%wip,notify=ALL", sc.owner); | |
| assertThat(sender) | |
| .sent("newpatchset", sc) | |
| .to(sc.reviewer) | |
| .cc(sc.ccer) | |
| .cc(StagedUsers.REVIEWER_BY_EMAIL, StagedUsers.CC_BY_EMAIL) | |
| .bcc(sc.starrer) | |
| .bcc(NEW_PATCHSETS) | |
| .noOneElse(); | |
| assertThat(sender).didNotSend(); | |
| } | |
| @Test | |
| public void newPatchSetOnWipChangeToReady() throws Exception { | |
| StagedChange sc = stageWipChange(); | |
| pushTo(sc, "refs/for/master%ready", sc.owner); | |
| assertThat(sender) | |
| .sent("newpatchset", sc) | |
| .to(sc.reviewer) | |
| .cc(sc.ccer) | |
| .cc(StagedUsers.REVIEWER_BY_EMAIL, StagedUsers.CC_BY_EMAIL) | |
| .bcc(sc.starrer) | |
| .bcc(NEW_PATCHSETS) | |
| .noOneElse(); | |
| assertThat(sender).didNotSend(); | |
| } | |
| @Test | |
| public void newPatchSetOnReviewableWipChange() throws Exception { | |
| StagedChange sc = stageReviewableWipChange(); | |
| pushTo(sc, "refs/for/master%wip", sc.owner); | |
| assertThat(sender).didNotSend(); | |
| } | |
| @Test | |
| public void newPatchSetOnReviewableChangeAddingReviewer() throws Exception { | |
| StagedChange sc = stageReviewableChange(); | |
| TestAccount newReviewer = sc.testAccount("newReviewer"); | |
| pushTo(sc, "refs/for/master%r=" + newReviewer.username(), sc.owner); | |
| assertThat(sender) | |
| .sent("newpatchset", sc) | |
| .to(sc.reviewer, newReviewer) | |
| .cc(sc.ccer) | |
| .cc(StagedUsers.REVIEWER_BY_EMAIL, StagedUsers.CC_BY_EMAIL) | |
| .bcc(sc.starrer) | |
| .bcc(NEW_PATCHSETS) | |
| .noOneElse(); | |
| assertThat(sender).didNotSend(); | |
| } | |
| @Test | |
| public void newPatchSetOnWipChangeAddingReviewer() throws Exception { | |
| StagedChange sc = stageWipChange(); | |
| TestAccount newReviewer = sc.testAccount("newReviewer"); | |
| pushTo(sc, "refs/for/master%r=" + newReviewer.username(), sc.owner); | |
| assertThat(sender).didNotSend(); | |
| } | |
| @Test | |
| public void newPatchSetOnWipChangeAddingReviewerNotifyAll() throws Exception { | |
| StagedChange sc = stageWipChange(); | |
| TestAccount newReviewer = sc.testAccount("newReviewer"); | |
| pushTo(sc, "refs/for/master%notify=ALL,r=" + newReviewer.username(), sc.owner); | |
| assertThat(sender) | |
| .sent("newpatchset", sc) | |
| .to(sc.reviewer, newReviewer) | |
| .cc(sc.ccer) | |
| .cc(StagedUsers.REVIEWER_BY_EMAIL, StagedUsers.CC_BY_EMAIL) | |
| .bcc(sc.starrer) | |
| .bcc(NEW_PATCHSETS) | |
| .noOneElse(); | |
| assertThat(sender).didNotSend(); | |
| } | |
| @Test | |
| public void newPatchSetOnWipChangeSettingReady() throws Exception { | |
| StagedChange sc = stageWipChange(); | |
| pushTo(sc, "refs/for/master%ready", sc.owner); | |
| assertThat(sender) | |
| .sent("newpatchset", sc) | |
| .to(sc.reviewer) | |
| .cc(sc.ccer) | |
| .cc(StagedUsers.REVIEWER_BY_EMAIL, StagedUsers.CC_BY_EMAIL) | |
| .bcc(sc.starrer) | |
| .bcc(NEW_PATCHSETS) | |
| .noOneElse(); | |
| assertThat(sender).didNotSend(); | |
| } | |
| private void pushTo(StagedChange sc, String ref, TestAccount by) throws Exception { | |
| pushTo(sc, ref, by, ENABLED); | |
| } | |
| private void pushTo(StagedChange sc, String ref, TestAccount by, EmailStrategy emailStrategy) | |
| throws Exception { | |
| setEmailStrategy(by, emailStrategy); | |
| // Use random file content to avoid that change kind is NO_CHANGE. | |
| String randomContent = UUID.randomUUID().toString(); | |
| pushFactory | |
| .create( | |
| by.newIdent(), | |
| sc.repo, | |
| "New Patch Set", | |
| PushOneCommit.FILE_NAME, | |
| randomContent, | |
| sc.changeId) | |
| .to(ref) | |
| .assertOkStatus(); | |
| } | |
| @Test | |
| public void editCommitMessageEditByOwnerOnReviewableChange() throws Exception { | |
| StagedChange sc = stageReviewableChange(); | |
| editCommitMessage(sc, sc.owner); | |
| assertThat(sender) | |
| .sent("newpatchset", sc) | |
| .to(sc.reviewer) | |
| .cc(sc.ccer) | |
| .cc(StagedUsers.REVIEWER_BY_EMAIL, StagedUsers.CC_BY_EMAIL) | |
| .bcc(sc.starrer) | |
| .bcc(NEW_PATCHSETS) | |
| .noOneElse(); | |
| assertThat(sender).didNotSend(); | |
| } | |
| @Test | |
| public void editCommitMessageEditByOtherOnReviewableChange() throws Exception { | |
| StagedChange sc = stageReviewableChange(); | |
| editCommitMessage(sc, other); | |
| assertThat(sender) | |
| .sent("newpatchset", sc) | |
| .to(sc.owner, sc.reviewer) | |
| .cc(sc.ccer) | |
| .cc(StagedUsers.REVIEWER_BY_EMAIL, StagedUsers.CC_BY_EMAIL) | |
| .bcc(sc.starrer) | |
| .bcc(NEW_PATCHSETS) | |
| .noOneElse(); | |
| assertThat(sender).didNotSend(); | |
| } | |
| @Test | |
| public void editCommitMessageByOtherOnReviewableChangeOwnerSelfCc() throws Exception { | |
| StagedChange sc = stageReviewableChange(); | |
| editCommitMessage(sc, other, CC_ON_OWN_COMMENTS); | |
| assertThat(sender) | |
| .sent("newpatchset", sc) | |
| .to(sc.owner, sc.reviewer, other) | |
| .cc(sc.ccer) | |
| .cc(StagedUsers.REVIEWER_BY_EMAIL, StagedUsers.CC_BY_EMAIL) | |
| .bcc(sc.starrer) | |
| .bcc(NEW_PATCHSETS) | |
| .noOneElse(); | |
| assertThat(sender).didNotSend(); | |
| } | |
| @Test | |
| public void editCommitMessageByOtherOnReviewableChangeNotifyOwnerReviewers() throws Exception { | |
| StagedChange sc = stageReviewableChange(); | |
| editCommitMessage(sc, other, OWNER_REVIEWERS); | |
| assertThat(sender) | |
| .sent("newpatchset", sc) | |
| .to(sc.owner, sc.reviewer) | |
| .cc(sc.ccer) | |
| .cc(StagedUsers.REVIEWER_BY_EMAIL, StagedUsers.CC_BY_EMAIL) | |
| .noOneElse(); | |
| assertThat(sender).didNotSend(); | |
| } | |
| @Test | |
| public void editCommitMessageByOtherOnReviewableChangeOwnerSelfCcNotifyOwnerReviewers() | |
| throws Exception { | |
| StagedChange sc = stageReviewableChange(); | |
| editCommitMessage(sc, other, OWNER_REVIEWERS, CC_ON_OWN_COMMENTS); | |
| assertThat(sender) | |
| .sent("newpatchset", sc) | |
| .to(sc.owner, sc.reviewer) | |
| .cc(sc.ccer, other) | |
| .cc(StagedUsers.REVIEWER_BY_EMAIL, StagedUsers.CC_BY_EMAIL) | |
| .noOneElse(); | |
| assertThat(sender).didNotSend(); | |
| } | |
| @Test | |
| public void editCommitMessageByOtherOnReviewableChangeNotifyOwner() throws Exception { | |
| StagedChange sc = stageReviewableChange(); | |
| editCommitMessage(sc, other, OWNER); | |
| assertThat(sender).sent("newpatchset", sc).to(sc.owner).noOneElse(); | |
| assertThat(sender).didNotSend(); | |
| } | |
| @Test | |
| public void editCommitMessageByOtherOnReviewableChangeOwnerSelfCcNotifyOwner() throws Exception { | |
| StagedChange sc = stageReviewableChange(); | |
| editCommitMessage(sc, other, OWNER, CC_ON_OWN_COMMENTS); | |
| assertThat(sender).sent("newpatchset", sc).to(sc.owner).cc(other).noOneElse(); | |
| assertThat(sender).didNotSend(); | |
| } | |
| @Test | |
| public void editCommitMessageByOtherOnReviewableChangeNotifyNone() throws Exception { | |
| StagedChange sc = stageReviewableChange(); | |
| editCommitMessage(sc, other, NONE); | |
| assertThat(sender).didNotSend(); | |
| } | |
| @Test | |
| public void editCommitMessageByOtherOnReviewableChangeOwnerSelfCcNotifyNone() throws Exception { | |
| StagedChange sc = stageReviewableChange(); | |
| editCommitMessage(sc, other, NONE, CC_ON_OWN_COMMENTS); | |
| assertThat(sender).didNotSend(); | |
| } | |
| @Test | |
| public void editCommitMessageOnWipChange() throws Exception { | |
| StagedChange sc = stageWipChange(); | |
| editCommitMessage(sc, sc.owner); | |
| assertThat(sender).didNotSend(); | |
| } | |
| @Test | |
| public void editCommitMessageByOtherOnWipChange() throws Exception { | |
| StagedChange sc = stageWipChange(); | |
| editCommitMessage(sc, other); | |
| assertThat(sender).sent("newpatchset", sc).to(sc.owner).noOneElse(); | |
| assertThat(sender).didNotSend(); | |
| } | |
| @Test | |
| public void editCommitMessageByOtherOnWipChangeSelfCc() throws Exception { | |
| StagedChange sc = stageWipChange(); | |
| editCommitMessage(sc, other, CC_ON_OWN_COMMENTS); | |
| assertThat(sender).sent("newpatchset", sc).to(sc.owner).cc(other).noOneElse(); | |
| assertThat(sender).didNotSend(); | |
| } | |
| @Test | |
| public void editCommitMessageOnWipChangeNotifyAll() throws Exception { | |
| StagedChange sc = stageWipChange(); | |
| editCommitMessage(sc, sc.owner, ALL); | |
| assertThat(sender) | |
| .sent("newpatchset", sc) | |
| .to(sc.reviewer) | |
| .cc(sc.ccer) | |
| .cc(StagedUsers.REVIEWER_BY_EMAIL, StagedUsers.CC_BY_EMAIL) | |
| .bcc(sc.starrer) | |
| .bcc(NEW_PATCHSETS) | |
| .noOneElse(); | |
| assertThat(sender).didNotSend(); | |
| } | |
| private void editCommitMessage(StagedChange sc, TestAccount by) throws Exception { | |
| editCommitMessage(sc, by, null, ENABLED); | |
| } | |
| private void editCommitMessage(StagedChange sc, TestAccount by, @Nullable NotifyHandling notify) | |
| throws Exception { | |
| editCommitMessage(sc, by, notify, ENABLED); | |
| } | |
| private void editCommitMessage(StagedChange sc, TestAccount by, EmailStrategy emailStrategy) | |
| throws Exception { | |
| editCommitMessage(sc, by, null, emailStrategy); | |
| } | |
| private void editCommitMessage( | |
| StagedChange sc, TestAccount by, @Nullable NotifyHandling notify, EmailStrategy emailStrategy) | |
| throws Exception { | |
| setEmailStrategy(by, emailStrategy); | |
| CommitInfo commit = gApi.changes().id(sc.changeId).current().commit(false); | |
| CommitMessageInput in = new CommitMessageInput(); | |
| in.message = "update\n" + commit.message; | |
| in.notify = notify; | |
| gApi.changes().id(sc.changeId).setMessage(in); | |
| } | |
| /* | |
| * RestoredSender tests. | |
| */ | |
| @Test | |
| public void restoreReviewableChange() throws Exception { | |
| StagedChange sc = stageAbandonedReviewableChange(); | |
| restore(sc.changeId, sc.owner); | |
| assertThat(sender) | |
| .sent("restore", sc) | |
| .cc(sc.reviewer, sc.ccer) | |
| .cc(StagedUsers.REVIEWER_BY_EMAIL, StagedUsers.CC_BY_EMAIL) | |
| .bcc(sc.starrer) | |
| .bcc(ALL_COMMENTS) | |
| .noOneElse(); | |
| assertThat(sender).didNotSend(); | |
| } | |
| @Test | |
| public void restoreReviewableWipChange() throws Exception { | |
| StagedChange sc = stageAbandonedReviewableWipChange(); | |
| restore(sc.changeId, sc.owner); | |
| assertThat(sender) | |
| .sent("restore", sc) | |
| .cc(sc.reviewer, sc.ccer) | |
| .cc(StagedUsers.REVIEWER_BY_EMAIL, StagedUsers.CC_BY_EMAIL) | |
| .bcc(sc.starrer) | |
| .bcc(ALL_COMMENTS) | |
| .noOneElse(); | |
| assertThat(sender).didNotSend(); | |
| } | |
| @Test | |
| public void restoreWipChange() throws Exception { | |
| StagedChange sc = stageAbandonedWipChange(); | |
| restore(sc.changeId, sc.owner); | |
| assertThat(sender) | |
| .sent("restore", sc) | |
| .cc(sc.reviewer, sc.ccer) | |
| .cc(StagedUsers.REVIEWER_BY_EMAIL, StagedUsers.CC_BY_EMAIL) | |
| .bcc(sc.starrer) | |
| .bcc(ALL_COMMENTS) | |
| .noOneElse(); | |
| assertThat(sender).didNotSend(); | |
| } | |
| @Test | |
| public void restoreReviewableChangeByAdmin() throws Exception { | |
| StagedChange sc = stageAbandonedReviewableChange(); | |
| restore(sc.changeId, admin); | |
| assertThat(sender) | |
| .sent("restore", sc) | |
| .to(sc.owner) | |
| .cc(sc.reviewer, sc.ccer) | |
| .cc(StagedUsers.REVIEWER_BY_EMAIL, StagedUsers.CC_BY_EMAIL) | |
| .bcc(sc.starrer) | |
| .bcc(ALL_COMMENTS) | |
| .noOneElse(); | |
| assertThat(sender).didNotSend(); | |
| } | |
| @Test | |
| public void restoreReviewableChangeByOwnerCcingSelf() throws Exception { | |
| StagedChange sc = stageAbandonedReviewableChange(); | |
| restore(sc.changeId, sc.owner, CC_ON_OWN_COMMENTS); | |
| assertThat(sender) | |
| .sent("restore", sc) | |
| .to(sc.owner) | |
| .cc(sc.reviewer, sc.ccer) | |
| .cc(StagedUsers.REVIEWER_BY_EMAIL, StagedUsers.CC_BY_EMAIL) | |
| .bcc(sc.starrer) | |
| .bcc(ALL_COMMENTS) | |
| .noOneElse(); | |
| assertThat(sender).didNotSend(); | |
| } | |
| @Test | |
| public void restoreReviewableChangeByAdminCcingSelf() throws Exception { | |
| StagedChange sc = stageAbandonedReviewableChange(); | |
| restore(sc.changeId, admin, CC_ON_OWN_COMMENTS); | |
| assertThat(sender) | |
| .sent("restore", sc) | |
| .to(sc.owner) | |
| .cc(sc.reviewer, sc.ccer, admin) | |
| .cc(StagedUsers.REVIEWER_BY_EMAIL, StagedUsers.CC_BY_EMAIL) | |
| .bcc(sc.starrer) | |
| .bcc(ALL_COMMENTS) | |
| .noOneElse(); | |
| assertThat(sender).didNotSend(); | |
| } | |
| private void restore(String changeId, TestAccount by) throws Exception { | |
| restore(changeId, by, ENABLED); | |
| } | |
| private void restore(String changeId, TestAccount by, EmailStrategy emailStrategy) | |
| throws Exception { | |
| setEmailStrategy(by, emailStrategy); | |
| requestScopeOperations.setApiUser(by.id()); | |
| gApi.changes().id(changeId).restore(); | |
| } | |
| /* | |
| * RevertedSender tests. | |
| */ | |
| @Test | |
| public void revertChangeByOwner() throws Exception { | |
| StagedChange sc = stageChange(); | |
| revert(sc, sc.owner); | |
| // email for the newly created revert change | |
| assertThat(sender) | |
| .sent("newchange", sc) | |
| .to(sc.reviewer, admin) | |
| .cc(sc.ccer) | |
| .bcc(sc.watchingProjectOwner) | |
| .bcc(NEW_CHANGES, NEW_PATCHSETS) | |
| .noOneElse(); | |
| // email for the change that is reverted | |
| assertThat(sender) | |
| .sent("revert", sc) | |
| .cc(sc.reviewer, sc.ccer, admin) | |
| .cc(StagedUsers.REVIEWER_BY_EMAIL, StagedUsers.CC_BY_EMAIL) | |
| .bcc(sc.starrer) | |
| .bcc(ALL_COMMENTS) | |
| .noOneElse(); | |
| assertThat(sender).didNotSend(); | |
| } | |
| @Test | |
| public void revertChangeByOwnerCcingSelf() throws Exception { | |
| StagedChange sc = stageChange(); | |
| revert(sc, sc.owner, CC_ON_OWN_COMMENTS); | |
| // email for the newly created revert change | |
| assertThat(sender) | |
| .sent("newchange", sc) | |
| .to(sc.reviewer, admin) | |
| .cc(sc.owner, sc.ccer) | |
| .bcc(sc.watchingProjectOwner) | |
| .bcc(NEW_CHANGES, NEW_PATCHSETS) | |
| .noOneElse(); | |
| // email for the change that is reverted | |
| assertThat(sender) | |
| .sent("revert", sc) | |
| .to(sc.owner) | |
| .cc(sc.reviewer, sc.ccer, admin) | |
| .cc(StagedUsers.REVIEWER_BY_EMAIL, StagedUsers.CC_BY_EMAIL) | |
| .bcc(sc.starrer) | |
| .bcc(ALL_COMMENTS) | |
| .noOneElse(); | |
| assertThat(sender).didNotSend(); | |
| } | |
| @Test | |
| public void revertChangeByOther() throws Exception { | |
| StagedChange sc = stageChange(); | |
| revert(sc, other); | |
| // email for the newly created revert change | |
| assertThat(sender) | |
| .sent("newchange", sc) | |
| .to(sc.owner, sc.reviewer, admin) | |
| .cc(sc.ccer) | |
| .bcc(sc.watchingProjectOwner) | |
| .bcc(NEW_CHANGES, NEW_PATCHSETS) | |
| .noOneElse(); | |
| // email for the change that is reverted | |
| assertThat(sender) | |
| .sent("revert", sc) | |
| .to(sc.owner) | |
| .cc(sc.reviewer, sc.ccer, admin) | |
| .cc(StagedUsers.REVIEWER_BY_EMAIL, StagedUsers.CC_BY_EMAIL) | |
| .bcc(sc.starrer) | |
| .bcc(ALL_COMMENTS) | |
| .noOneElse(); | |
| assertThat(sender).didNotSend(); | |
| } | |
| @Test | |
| public void revertChangeByOtherCcingSelf() throws Exception { | |
| StagedChange sc = stageChange(); | |
| revert(sc, other, CC_ON_OWN_COMMENTS); | |
| // email for the newly created revert change | |
| assertThat(sender) | |
| .sent("newchange", sc) | |
| .to(sc.owner, sc.reviewer, admin) | |
| .cc(sc.ccer, other) | |
| .bcc(sc.watchingProjectOwner) | |
| .bcc(NEW_CHANGES, NEW_PATCHSETS) | |
| .noOneElse(); | |
| // email for the change that is reverted | |
| assertThat(sender) | |
| .sent("revert", sc) | |
| .to(sc.owner) | |
| .cc(other, sc.reviewer, sc.ccer, admin) | |
| .cc(StagedUsers.REVIEWER_BY_EMAIL, StagedUsers.CC_BY_EMAIL) | |
| .bcc(sc.starrer) | |
| .bcc(ALL_COMMENTS) | |
| .noOneElse(); | |
| assertThat(sender).didNotSend(); | |
| } | |
| private StagedChange stageChange() throws Exception { | |
| StagedChange sc = stageReviewableChange(); | |
| requestScopeOperations.setApiUser(admin.id()); | |
| gApi.changes().id(sc.changeId).current().review(ReviewInput.approve()); | |
| gApi.changes().id(sc.changeId).current().submit(); | |
| sender.clear(); | |
| return sc; | |
| } | |
| private void revert(StagedChange sc, TestAccount by) throws Exception { | |
| revert(sc, by, ENABLED); | |
| } | |
| private void revert(StagedChange sc, TestAccount by, EmailStrategy emailStrategy) | |
| throws Exception { | |
| setEmailStrategy(by, emailStrategy); | |
| requestScopeOperations.setApiUser(by.id()); | |
| gApi.changes().id(sc.changeId).revert(); | |
| } | |
| /* | |
| * Start review and WIP tests. | |
| */ | |
| @Test | |
| public void startReviewOnWipChange() throws Exception { | |
| StagedChange sc = stageWipChange(); | |
| startReview(sc); | |
| assertThat(sender) | |
| .sent("comment", sc) | |
| .cc(sc.reviewer, sc.ccer) | |
| .cc(StagedUsers.REVIEWER_BY_EMAIL, StagedUsers.CC_BY_EMAIL) | |
| .bcc(sc.starrer) | |
| .bcc(ALL_COMMENTS) | |
| .noOneElse(); | |
| assertThat(sender).didNotSend(); | |
| } | |
| @Test | |
| public void startReviewOnWipChangeCcingSelf() throws Exception { | |
| StagedChange sc = stageWipChange(); | |
| setEmailStrategy(sc.owner, CC_ON_OWN_COMMENTS); | |
| startReview(sc); | |
| assertThat(sender) | |
| .sent("comment", sc) | |
| .to(sc.owner) | |
| .cc(sc.reviewer, sc.ccer) | |
| .cc(StagedUsers.REVIEWER_BY_EMAIL, StagedUsers.CC_BY_EMAIL) | |
| .bcc(sc.starrer) | |
| .bcc(ALL_COMMENTS) | |
| .noOneElse(); | |
| assertThat(sender).didNotSend(); | |
| } | |
| @Test | |
| public void setWorkInProgress() throws Exception { | |
| StagedChange sc = stageReviewableChange(); | |
| gApi.changes().id(sc.changeId).setWorkInProgress(); | |
| assertThat(sender).didNotSend(); | |
| } | |
| private void startReview(StagedChange sc) throws Exception { | |
| requestScopeOperations.setApiUser(sc.owner.id()); | |
| gApi.changes().id(sc.changeId).setReadyForReview(); | |
| } | |
| private void setWorkInProgressByDefault(Project.NameKey p, InheritableBoolean v) | |
| throws Exception { | |
| ConfigInput input = new ConfigInput(); | |
| input.workInProgressByDefault = v; | |
| gApi.projects().name(p.get()).config(input); | |
| } | |
| } |