| // Copyright (C) 2019 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.plugins.checks.acceptance.api; |
| |
| import static com.google.common.collect.ImmutableList.toImmutableList; |
| import static com.google.common.truth.Truth.assertThat; |
| import static com.google.gerrit.acceptance.testsuite.project.TestProjectUpdate.allowCapability; |
| import static java.util.stream.Collectors.toList; |
| import static java.util.stream.Collectors.toMap; |
| |
| import com.google.common.base.Joiner; |
| import com.google.common.collect.ImmutableList; |
| import com.google.common.collect.ImmutableListMultimap; |
| import com.google.common.collect.ImmutableMap; |
| import com.google.common.collect.ImmutableSet; |
| import com.google.gerrit.acceptance.PushOneCommit; |
| import com.google.gerrit.acceptance.TestAccount; |
| import com.google.gerrit.acceptance.testsuite.group.GroupOperations; |
| 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.AccountGroup; |
| import com.google.gerrit.entities.Change; |
| import com.google.gerrit.entities.PatchSet; |
| import com.google.gerrit.extensions.api.changes.NotifyHandling; |
| import com.google.gerrit.extensions.api.changes.NotifyInfo; |
| import com.google.gerrit.extensions.api.changes.RecipientType; |
| import com.google.gerrit.extensions.client.ProjectWatchInfo; |
| import com.google.gerrit.extensions.common.ChangeInfo; |
| import com.google.gerrit.extensions.common.PluginDefinedInfo; |
| import com.google.gerrit.extensions.restapi.RestApiException; |
| import com.google.gerrit.plugins.checks.CheckKey; |
| import com.google.gerrit.plugins.checks.CheckerUuid; |
| import com.google.gerrit.plugins.checks.acceptance.AbstractCheckersTest; |
| import com.google.gerrit.plugins.checks.api.ChangeCheckInfo; |
| import com.google.gerrit.plugins.checks.api.CheckInput; |
| import com.google.gerrit.plugins.checks.api.CheckState; |
| import com.google.gerrit.plugins.checks.api.CombinedCheckState; |
| import com.google.gerrit.plugins.checks.api.RerunInput; |
| import com.google.gerrit.testing.FakeEmailSender.Message; |
| import com.google.inject.Inject; |
| import java.util.Arrays; |
| import java.util.HashMap; |
| import java.util.List; |
| import java.util.Map; |
| import java.util.Set; |
| import org.junit.Before; |
| import org.junit.Test; |
| |
| public class ChecksEmailIT extends AbstractCheckersTest { |
| @Inject private RequestScopeOperations requestScopeOperations; |
| @Inject private GroupOperations groupOperations; |
| @Inject private ProjectOperations projectOperations; |
| |
| private static final String GERRIT_MESSAGE_TYPE_COMBINED_CHECK_STATE_UPDATE = |
| "Gerrit-MessageType: combinedCheckStateUpdate"; |
| |
| private TestAccount bot; |
| private TestAccount owner; |
| private TestAccount ignoringReviewer; |
| private TestAccount reviewer; |
| private TestAccount starrer; |
| private TestAccount watcher; |
| private Change change; |
| private PatchSet.Id patchSetId; |
| |
| @Before |
| public void setup() throws Exception { |
| // Create a bot account, create a bots group and add the bot as member and allow the bots group |
| // to post checks. |
| bot = accountCreator.create("bot", "bot@example.com", "Bot", null); |
| AccountGroup.UUID botsAccountGroupUuid = |
| groupOperations.newGroup().name("bots").addMember(bot.id()).create(); |
| projectOperations |
| .project(allProjects) |
| .forUpdate() |
| .add(allowCapability("checks-administrateCheckers").group(botsAccountGroupUuid)) |
| .update(); |
| |
| // Create a change. |
| owner = admin; |
| PushOneCommit.Result result = createChange(); |
| change = result.getChange().change(); |
| patchSetId = result.getPatchSetId(); |
| |
| // Add a reviewer. |
| reviewer = accountCreator.create("reviewer", "reviewer@example.com", "Reviewer", null); |
| gApi.changes().id(patchSetId.changeId().get()).addReviewer(reviewer.username()); |
| |
| // Star the change from some user. |
| starrer = accountCreator.create("starred", "starrer@example.com", "Starrer", null); |
| requestScopeOperations.setApiUser(starrer.id()); |
| gApi.accounts().self().starChange(patchSetId.changeId().toString()); |
| |
| // Watch all comments of change from some user. |
| watcher = accountCreator.create("watcher", "watcher@example.com", "Watcher", null); |
| requestScopeOperations.setApiUser(watcher.id()); |
| ProjectWatchInfo projectWatchInfo = new ProjectWatchInfo(); |
| projectWatchInfo.project = project.get(); |
| projectWatchInfo.filter = "*"; |
| projectWatchInfo.notifyAllComments = true; |
| gApi.accounts().self().setWatchedProjects(ImmutableList.of(projectWatchInfo)); |
| |
| // Watch only change creations from some user --> user doesn't get notified by checks plugin. |
| TestAccount changeCreationWatcher = |
| accountCreator.create( |
| "changeCreationWatcher", |
| "changeCreationWatcher@example.com", |
| "Change Creation Watcher", |
| null); |
| requestScopeOperations.setApiUser(changeCreationWatcher.id()); |
| projectWatchInfo = new ProjectWatchInfo(); |
| projectWatchInfo.project = project.get(); |
| projectWatchInfo.filter = "*"; |
| projectWatchInfo.notifyNewChanges = true; |
| gApi.accounts().self().setWatchedProjects(ImmutableList.of(projectWatchInfo)); |
| |
| // Add a reviewer that ignores the change --> user doesn't get notified by checks plugin. |
| ignoringReviewer = accountCreator.create("ignorer", "ignorer@example.com", "Ignorer", null); |
| requestScopeOperations.setApiUser(admin.id()); |
| gApi.changes().id(patchSetId.changeId().get()).addReviewer(ignoringReviewer.username()); |
| requestScopeOperations.setApiUser(ignoringReviewer.id()); |
| gApi.changes().id(patchSetId.changeId().get()).ignore(true); |
| |
| // Reset request scope to admin. |
| requestScopeOperations.setApiUser(admin.id()); |
| } |
| |
| @Test |
| public void combinedCheckUpdatedEmailAfterCheckCreationToOwnerOnly() throws Exception { |
| // Create a required checker. |
| CheckerUuid checkerUuid = |
| checkerOperations.newChecker().repository(project).required().create(); |
| |
| assertThat(getCombinedCheckState()).isEqualTo(CombinedCheckState.IN_PROGRESS); |
| |
| sender.clear(); |
| |
| // Post a new check that changes the combined check state to FAILED. |
| requestScopeOperations.setApiUser(bot.id()); |
| CheckInput input = new CheckInput(); |
| input.checkerUuid = checkerUuid.get(); |
| input.state = CheckState.FAILED; |
| checksApiFactory.revision(patchSetId).create(input).get(); |
| assertThat(getCombinedCheckState()).isEqualTo(CombinedCheckState.FAILED); |
| |
| // Expect email because the combined check state was updated. |
| // The email is only sent to the change owner because the new combined check state != |
| // SUCCESSFUL. |
| List<Message> messages = sender.getMessages(); |
| assertThat(messages).hasSize(1); |
| |
| Message message = messages.get(0); |
| assertThat(message.from().name()).isEqualTo(bot.fullName() + " (Code Review)"); |
| assertThat(message.body()) |
| .contains("The combined check state has been updated to " + CombinedCheckState.FAILED); |
| assertThat(message.rcpt()).containsExactly(owner.getNameEmail()); |
| } |
| |
| @Test |
| public void combinedCheckUpdatedEmailAfterCheckCreationToAll() throws Exception { |
| // Create a required checker. |
| CheckerUuid checkerUuid = |
| checkerOperations.newChecker().repository(project).required().create(); |
| |
| assertThat(getCombinedCheckState()).isEqualTo(CombinedCheckState.IN_PROGRESS); |
| |
| sender.clear(); |
| |
| // Post a check that changes the combined check state to SUCCESSFUL. |
| requestScopeOperations.setApiUser(bot.id()); |
| CheckInput input = new CheckInput(); |
| input.checkerUuid = checkerUuid.get(); |
| input.state = CheckState.SUCCESSFUL; |
| checksApiFactory.revision(patchSetId).create(input).get(); |
| assertThat(getCombinedCheckState()).isEqualTo(CombinedCheckState.SUCCESSFUL); |
| |
| // Expect email because the combined check state was updated. |
| // The email is only sent to all users that are involved in the change because the new combined |
| // check state = SUCCESSFUL. |
| List<Message> messages = sender.getMessages(); |
| assertThat(messages).hasSize(1); |
| |
| Message message = messages.get(0); |
| assertThat(message.from().name()).isEqualTo(bot.fullName() + " (Code Review)"); |
| assertThat(message.body()) |
| .contains("The combined check state has been updated to " + CombinedCheckState.SUCCESSFUL); |
| assertThat(message.rcpt()) |
| .containsExactly( |
| owner.getNameEmail(), |
| reviewer.getNameEmail(), |
| starrer.getNameEmail(), |
| watcher.getNameEmail()); |
| } |
| |
| @Test |
| public void noCombinedCheckUpdatedEmailOnCheckCreationIfCombinedCheckStateIsNotChanged() |
| throws Exception { |
| // Create two required checkers. |
| CheckerUuid checkerUuid1 = |
| checkerOperations.newChecker().repository(project).required().create(); |
| CheckerUuid checkerUuid2 = |
| checkerOperations.newChecker().repository(project).required().create(); |
| |
| // Create a check that sets the combined check state to FAILED. |
| CheckKey checkKey = CheckKey.create(project, patchSetId, checkerUuid1); |
| checkOperations.newCheck(checkKey).state(CheckState.FAILED).upsert(); |
| assertThat(getCombinedCheckState()).isEqualTo(CombinedCheckState.FAILED); |
| |
| sender.clear(); |
| |
| // Post a new check that doesn't change the combined check state.. |
| requestScopeOperations.setApiUser(bot.id()); |
| CheckInput input = new CheckInput(); |
| input.checkerUuid = checkerUuid2.get(); |
| input.state = CheckState.SCHEDULED; |
| checksApiFactory.revision(patchSetId).create(input).get(); |
| assertThat(getCombinedCheckState()).isEqualTo(CombinedCheckState.FAILED); |
| |
| // Expect that no email was sent because the combined check state was not updated. |
| assertThat(sender.getMessages()).isEmpty(); |
| } |
| |
| @Test |
| public void combinedCheckUpdatedEmailAfterCheckUpdateToOwnerOnly() throws Exception { |
| // Create a required checker. |
| CheckerUuid checkerUuid = |
| checkerOperations.newChecker().repository(project).required().create(); |
| |
| // Create a check that sets the combined check state to FAILED. |
| CheckKey checkKey = CheckKey.create(project, patchSetId, checkerUuid); |
| checkOperations.newCheck(checkKey).state(CheckState.FAILED).upsert(); |
| assertThat(getCombinedCheckState()).isEqualTo(CombinedCheckState.FAILED); |
| |
| sender.clear(); |
| |
| // Update the new check so that the combined check state is changed to IN_PROGRESS. |
| requestScopeOperations.setApiUser(bot.id()); |
| CheckInput input = new CheckInput(); |
| input.checkerUuid = checkerUuid.get(); |
| input.state = CheckState.RUNNING; |
| checksApiFactory.revision(patchSetId).create(input).get(); |
| assertThat(getCombinedCheckState()).isEqualTo(CombinedCheckState.IN_PROGRESS); |
| |
| // Expect email because the combined check state was updated. |
| // The email is only sent to the change owner because the new combined check state != |
| // SUCCESSFUL. |
| List<Message> messages = sender.getMessages(); |
| assertThat(messages).hasSize(1); |
| |
| Message message = messages.get(0); |
| assertThat(message.from().name()).isEqualTo(bot.fullName() + " (Code Review)"); |
| assertThat(message.body()) |
| .contains("The combined check state has been updated to " + CombinedCheckState.IN_PROGRESS); |
| assertThat(message.rcpt()).containsExactly(owner.getNameEmail()); |
| } |
| |
| @Test |
| public void combinedCheckUpdatedEmailAfterCheckUpdateToAll() throws Exception { |
| // Create a required checker. |
| CheckerUuid checkerUuid = |
| checkerOperations.newChecker().repository(project).required().create(); |
| |
| // Create a check that sets the combined check state to FAILED. |
| CheckKey checkKey = CheckKey.create(project, patchSetId, checkerUuid); |
| checkOperations.newCheck(checkKey).state(CheckState.FAILED).upsert(); |
| assertThat(getCombinedCheckState()).isEqualTo(CombinedCheckState.FAILED); |
| |
| sender.clear(); |
| |
| // Update the new check so that the combined check state is changed to IN_PROGRESS. |
| requestScopeOperations.setApiUser(bot.id()); |
| CheckInput input = new CheckInput(); |
| input.checkerUuid = checkerUuid.get(); |
| input.state = CheckState.SUCCESSFUL; |
| checksApiFactory.revision(patchSetId).create(input).get(); |
| assertThat(getCombinedCheckState()).isEqualTo(CombinedCheckState.SUCCESSFUL); |
| |
| // Expect email because the combined check state was updated. |
| // The email is only sent to all users that are involved in the change because the new combined |
| // check state = SUCCESSFUL. |
| List<Message> messages = sender.getMessages(); |
| assertThat(messages).hasSize(1); |
| |
| Message message = messages.get(0); |
| assertThat(message.from().name()).isEqualTo(bot.fullName() + " (Code Review)"); |
| assertThat(message.body()) |
| .contains("The combined check state has been updated to " + CombinedCheckState.SUCCESSFUL); |
| assertThat(message.rcpt()) |
| .containsExactly( |
| owner.getNameEmail(), |
| reviewer.getNameEmail(), |
| starrer.getNameEmail(), |
| watcher.getNameEmail()); |
| } |
| |
| @Test |
| public void noCombinedCheckUpdatedEmailOnCheckUpdateIfCombinedCheckStateIsNotChanged() |
| throws Exception { |
| // Create two required checkers. |
| CheckerUuid checkerUuid1 = |
| checkerOperations.newChecker().repository(project).required().create(); |
| CheckerUuid checkerUuid2 = |
| checkerOperations.newChecker().repository(project).required().create(); |
| |
| // Create 2 checks that set the combined check state to FAILED. |
| CheckKey checkKey1 = CheckKey.create(project, patchSetId, checkerUuid1); |
| checkOperations.newCheck(checkKey1).state(CheckState.FAILED).upsert(); |
| CheckKey checkKey2 = CheckKey.create(project, patchSetId, checkerUuid2); |
| checkOperations.newCheck(checkKey2).state(CheckState.FAILED).upsert(); |
| assertThat(getCombinedCheckState()).isEqualTo(CombinedCheckState.FAILED); |
| |
| sender.clear(); |
| |
| // Update one of the checks in a way so that doesn't change the combined check state. |
| requestScopeOperations.setApiUser(bot.id()); |
| CheckInput input = new CheckInput(); |
| input.checkerUuid = checkerUuid2.get(); |
| input.state = CheckState.SCHEDULED; |
| checksApiFactory.revision(patchSetId).create(input).get(); |
| assertThat(getCombinedCheckState()).isEqualTo(CombinedCheckState.FAILED); |
| |
| // Expect that no email was sent because the combined check state was not updated. |
| assertThat(sender.getMessages()).isEmpty(); |
| } |
| |
| @Test |
| public void combinedCheckUpdatedEmailAfterCheckRerunToOwnerOnly() throws Exception { |
| // Create a required checker. |
| CheckerUuid checkerUuid = |
| checkerOperations.newChecker().repository(project).required().create(); |
| |
| // Create a check that sets the combined check state to FAILED. |
| CheckKey checkKey = CheckKey.create(project, patchSetId, checkerUuid); |
| checkOperations.newCheck(checkKey).state(CheckState.FAILED).upsert(); |
| assertThat(getCombinedCheckState()).isEqualTo(CombinedCheckState.FAILED); |
| |
| sender.clear(); |
| |
| // Rerun the check so that the combined check state is changed to IN_PROGRESS. |
| requestScopeOperations.setApiUser(bot.id()); |
| checksApiFactory.revision(patchSetId).id(checkKey.checkerUuid()).rerun(); |
| assertThat(getCombinedCheckState()).isEqualTo(CombinedCheckState.IN_PROGRESS); |
| |
| // Expect email because the combined check state was updated. |
| // The email is only sent to the change owner because the new combined check state != |
| // SUCCESSFUL. |
| List<Message> messages = sender.getMessages(); |
| assertThat(messages).hasSize(1); |
| |
| Message message = messages.get(0); |
| assertThat(message.from().name()).isEqualTo(bot.fullName() + " (Code Review)"); |
| assertThat(message.body()) |
| .contains("The combined check state has been updated to " + CombinedCheckState.IN_PROGRESS); |
| assertThat(message.rcpt()).containsExactly(owner.getNameEmail()); |
| } |
| |
| @Test |
| public void noCombinedCheckUpdatedEmailOnCheckRerunIfCombinedCheckStateIsNotChanged() |
| throws Exception { |
| // Create two required checkers. |
| CheckerUuid checkerUuid1 = |
| checkerOperations.newChecker().repository(project).required().create(); |
| CheckerUuid checkerUuid2 = |
| checkerOperations.newChecker().repository(project).required().create(); |
| |
| // Create 2 checks that set the combined check state to FAILED. |
| CheckKey checkKey1 = CheckKey.create(project, patchSetId, checkerUuid1); |
| checkOperations.newCheck(checkKey1).state(CheckState.FAILED).upsert(); |
| CheckKey checkKey2 = CheckKey.create(project, patchSetId, checkerUuid2); |
| checkOperations.newCheck(checkKey2).state(CheckState.FAILED).upsert(); |
| assertThat(getCombinedCheckState()).isEqualTo(CombinedCheckState.FAILED); |
| |
| sender.clear(); |
| |
| // Rerun only one check so that the combined check state stays FAILED. |
| requestScopeOperations.setApiUser(bot.id()); |
| checksApiFactory.revision(patchSetId).id(checkKey1.checkerUuid()).rerun(); |
| assertThat(getCombinedCheckState()).isEqualTo(CombinedCheckState.FAILED); |
| |
| // Expect that no email was sent because the combined check state was not updated. |
| assertThat(sender.getMessages()).isEmpty(); |
| } |
| |
| @Test |
| public void postCheckRespectsNotifySettings() throws Exception { |
| // Create a required checker. |
| CheckerUuid checkerUuid = |
| checkerOperations.newChecker().repository(project).required().create(); |
| |
| testNotifySettingsForPostCheck( |
| checkerUuid, NotifyHandling.ALL, owner, reviewer, starrer, watcher); |
| testNotifySettingsForPostCheck(checkerUuid, NotifyHandling.OWNER, owner); |
| testNotifySettingsForPostCheck(checkerUuid, NotifyHandling.OWNER_REVIEWERS, owner, reviewer); |
| testNotifySettingsForPostCheck(checkerUuid, NotifyHandling.NONE); |
| |
| testNotifySettingsForPostCheck( |
| checkerUuid, |
| ImmutableSet.of(user), |
| NotifyHandling.ALL, |
| user, |
| owner, |
| reviewer, |
| starrer, |
| watcher); |
| testNotifySettingsForPostCheck( |
| checkerUuid, ImmutableSet.of(user), NotifyHandling.OWNER, user, owner); |
| testNotifySettingsForPostCheck( |
| checkerUuid, ImmutableSet.of(user), NotifyHandling.OWNER_REVIEWERS, user, owner, reviewer); |
| testNotifySettingsForPostCheck(checkerUuid, ImmutableSet.of(user), NotifyHandling.NONE, user); |
| } |
| |
| private void testNotifySettingsForPostCheck( |
| CheckerUuid checkerUuid, NotifyHandling notify, TestAccount... expectedRecipients) |
| throws RestApiException { |
| testNotifySettingsForPostCheck(checkerUuid, ImmutableSet.of(), notify, expectedRecipients); |
| } |
| |
| private void testNotifySettingsForPostCheck( |
| CheckerUuid checkerUuid, |
| Set<TestAccount> accountsToNotify, |
| NotifyHandling notify, |
| TestAccount... expectedRecipients) |
| throws RestApiException { |
| assertThat(getCombinedCheckState()).isEqualTo(CombinedCheckState.IN_PROGRESS); |
| |
| sender.clear(); |
| |
| // Post a new check that changes the combined check state to FAILED. |
| requestScopeOperations.setApiUser(bot.id()); |
| CheckInput input = new CheckInput(); |
| if (!accountsToNotify.isEmpty()) { |
| input.notifyDetails = |
| ImmutableMap.of( |
| RecipientType.TO, |
| new NotifyInfo( |
| accountsToNotify.stream().map(TestAccount::username).collect(toImmutableList()))); |
| } |
| input.notify = notify; |
| input.checkerUuid = checkerUuid.get(); |
| input.state = CheckState.FAILED; |
| checksApiFactory.revision(patchSetId).create(input).get(); |
| assertThat(getCombinedCheckState()).isEqualTo(CombinedCheckState.FAILED); |
| |
| List<Message> messages = sender.getMessages(); |
| if (expectedRecipients.length == 0) { |
| assertThat(messages).isEmpty(); |
| } else { |
| assertThat(messages).hasSize(1); |
| |
| Message message = messages.get(0); |
| assertThat(message.from().name()).isEqualTo(bot.fullName() + " (Code Review)"); |
| assertThat(message.body()) |
| .contains("The combined check state has been updated to " + CombinedCheckState.FAILED); |
| assertThat(message.rcpt()) |
| .containsExactlyElementsIn( |
| Arrays.stream(expectedRecipients) |
| .map(TestAccount::getNameEmail) |
| .collect(toImmutableList())); |
| } |
| |
| // reset combined check state |
| input.state = CheckState.SCHEDULED; |
| checksApiFactory.revision(patchSetId).create(input).get(); |
| assertThat(getCombinedCheckState()).isEqualTo(CombinedCheckState.IN_PROGRESS); |
| } |
| |
| @Test |
| public void rerunCheckRespectsNotifySettings() throws Exception { |
| // Create a required checker. |
| CheckerUuid checkerUuid = |
| checkerOperations.newChecker().repository(project).required().create(); |
| |
| testNotifySettingsForRerunCheck( |
| checkerUuid, NotifyHandling.ALL, owner, reviewer, starrer, watcher); |
| testNotifySettingsForRerunCheck(checkerUuid, NotifyHandling.OWNER, owner); |
| testNotifySettingsForRerunCheck(checkerUuid, NotifyHandling.OWNER_REVIEWERS, owner, reviewer); |
| testNotifySettingsForRerunCheck(checkerUuid, NotifyHandling.NONE); |
| |
| testNotifySettingsForRerunCheck( |
| checkerUuid, |
| ImmutableSet.of(user), |
| NotifyHandling.ALL, |
| user, |
| owner, |
| reviewer, |
| starrer, |
| watcher); |
| testNotifySettingsForRerunCheck( |
| checkerUuid, ImmutableSet.of(user), NotifyHandling.OWNER, user, owner); |
| testNotifySettingsForRerunCheck( |
| checkerUuid, ImmutableSet.of(user), NotifyHandling.OWNER_REVIEWERS, user, owner, reviewer); |
| testNotifySettingsForRerunCheck(checkerUuid, ImmutableSet.of(user), NotifyHandling.NONE, user); |
| } |
| |
| private void testNotifySettingsForRerunCheck( |
| CheckerUuid checkerUuid, NotifyHandling notify, TestAccount... expectedRecipients) |
| throws RestApiException { |
| testNotifySettingsForPostCheck(checkerUuid, ImmutableSet.of(), notify, expectedRecipients); |
| } |
| |
| private void testNotifySettingsForRerunCheck( |
| CheckerUuid checkerUuid, |
| Set<TestAccount> accountsToNotify, |
| NotifyHandling notify, |
| TestAccount... expectedRecipients) |
| throws RestApiException { |
| // Create a check that sets the combined check state to FAILED. |
| CheckKey checkKey = CheckKey.create(project, patchSetId, checkerUuid); |
| checkOperations.check(checkKey).forUpdate().state(CheckState.FAILED).upsert(); |
| assertThat(getCombinedCheckState()).isEqualTo(CombinedCheckState.FAILED); |
| |
| sender.clear(); |
| |
| // Post a new check that changes the combined check state to FAILED. |
| requestScopeOperations.setApiUser(bot.id()); |
| RerunInput rerunInput = new RerunInput(); |
| if (!accountsToNotify.isEmpty()) { |
| rerunInput.notifyDetails = |
| ImmutableMap.of( |
| RecipientType.TO, |
| new NotifyInfo( |
| accountsToNotify.stream().map(TestAccount::username).collect(toImmutableList()))); |
| } |
| rerunInput.notify = notify; |
| checksApiFactory.revision(patchSetId).id(checkKey.checkerUuid()).rerun(rerunInput); |
| assertThat(getCombinedCheckState()).isEqualTo(CombinedCheckState.IN_PROGRESS); |
| |
| List<Message> messages = sender.getMessages(); |
| if (expectedRecipients.length == 0) { |
| assertThat(messages).isEmpty(); |
| } else { |
| assertThat(messages).hasSize(1); |
| |
| Message message = messages.get(0); |
| assertThat(message.from().name()).isEqualTo(bot.fullName() + " (Code Review)"); |
| assertThat(message.body()) |
| .contains( |
| "The combined check state has been updated to " + CombinedCheckState.IN_PROGRESS); |
| assertThat(message.rcpt()) |
| .containsExactlyElementsIn( |
| Arrays.stream(expectedRecipients) |
| .map(TestAccount::getNameEmail) |
| .collect(toImmutableList())); |
| } |
| } |
| |
| @Test |
| public void verifyMessageBodiesForCombinedCheckStateUpdatedDefaultEmail() throws Exception { |
| String checkerName = "My Checker"; |
| CheckerUuid checkerUuid = |
| checkerOperations.newChecker().name(checkerName).repository(project).required().create(); |
| assertThat(getCombinedCheckState()).isEqualTo(CombinedCheckState.IN_PROGRESS); |
| |
| sender.clear(); |
| postCheck(checkerUuid, CheckState.SUCCESSFUL); |
| assertThat(getCombinedCheckState()).isEqualTo(CombinedCheckState.SUCCESSFUL); |
| |
| List<Message> messages = sender.getMessages(); |
| assertThat(messages).hasSize(1); |
| |
| Message message = messages.get(0); |
| assertThat(message.body()) |
| .contains( |
| combinedCheckStateUpdatedText(CombinedCheckState.SUCCESSFUL) |
| + allChecksOverviewText( |
| ImmutableMap.of(CheckState.SUCCESSFUL, ImmutableList.of(checkerName)))); |
| assertThat(message.body()).contains(GERRIT_MESSAGE_TYPE_COMBINED_CHECK_STATE_UPDATE); |
| |
| assertThat(message.htmlBody()) |
| .contains( |
| combinedCheckStateUpdatedHtml(CombinedCheckState.SUCCESSFUL) |
| + allChecksOverviewHtml( |
| ImmutableMap.of(CheckState.SUCCESSFUL, ImmutableList.of(checkerName)))); |
| assertThat(message.htmlBody()).contains(GERRIT_MESSAGE_TYPE_COMBINED_CHECK_STATE_UPDATE); |
| } |
| |
| @Test |
| public void verifyMessageBodiesForCombinedCheckStateUpdatedToFailedEmail() throws Exception { |
| String checkerName = "My Checker"; |
| CheckerUuid checkerUuid = |
| checkerOperations.newChecker().repository(project).name(checkerName).required().create(); |
| assertThat(getCombinedCheckState()).isEqualTo(CombinedCheckState.IN_PROGRESS); |
| |
| sender.clear(); |
| postCheck(checkerUuid, CheckState.FAILED); |
| assertThat(getCombinedCheckState()).isEqualTo(CombinedCheckState.FAILED); |
| |
| List<Message> messages = sender.getMessages(); |
| assertThat(messages).hasSize(1); |
| |
| Message message = messages.get(0); |
| assertThat(message.body()) |
| .contains( |
| combinedCheckStateUpdatedText(CombinedCheckState.FAILED) |
| + "\n" |
| + "Checker " |
| + checkerName |
| + " updated the check state to " |
| + CheckState.FAILED |
| + ".\n" |
| + allChecksOverviewText( |
| ImmutableMap.of(CheckState.FAILED, ImmutableList.of(checkerName)))); |
| assertThat(message.body()).contains(GERRIT_MESSAGE_TYPE_COMBINED_CHECK_STATE_UPDATE); |
| |
| assertThat(message.htmlBody()) |
| .contains( |
| combinedCheckStateUpdatedHtml(CombinedCheckState.FAILED) |
| + "<p>Checker <strong>" |
| + checkerName |
| + "</strong> updated the check state to " |
| + CheckState.FAILED |
| + ".</p>" |
| + allChecksOverviewHtml( |
| ImmutableMap.of(CheckState.FAILED, ImmutableList.of(checkerName)))); |
| assertThat(message.htmlBody()).contains(GERRIT_MESSAGE_TYPE_COMBINED_CHECK_STATE_UPDATE); |
| } |
| |
| @Test |
| public void verifyMessageBodiesForCombinedCheckStateUpdatedToFailedEmailWithCheckerUrl() |
| throws Exception { |
| String checkerName = "My Checker"; |
| String checkerUrl = "http://my-checker/"; |
| CheckerUuid checkerUuid = |
| checkerOperations |
| .newChecker() |
| .repository(project) |
| .name(checkerName) |
| .url(checkerUrl) |
| .required() |
| .create(); |
| assertThat(getCombinedCheckState()).isEqualTo(CombinedCheckState.IN_PROGRESS); |
| |
| sender.clear(); |
| postCheck(checkerUuid, CheckState.FAILED); |
| assertThat(getCombinedCheckState()).isEqualTo(CombinedCheckState.FAILED); |
| |
| List<Message> messages = sender.getMessages(); |
| assertThat(messages).hasSize(1); |
| |
| Message message = messages.get(0); |
| assertThat(message.body()) |
| .contains( |
| combinedCheckStateUpdatedText(CombinedCheckState.FAILED) |
| + "\n" |
| + "Checker " |
| + checkerName |
| + " ( " |
| + checkerUrl |
| + " ) updated the check state to " |
| + CheckState.FAILED |
| + ".\n" |
| + allChecksOverviewText( |
| ImmutableMap.of(CheckState.FAILED, ImmutableList.of(checkerName)))); |
| assertThat(message.body()).contains(GERRIT_MESSAGE_TYPE_COMBINED_CHECK_STATE_UPDATE); |
| |
| assertThat(message.htmlBody()) |
| .contains( |
| combinedCheckStateUpdatedHtml(CombinedCheckState.FAILED) |
| + "<p>Checker <a href=\"" |
| + checkerUrl |
| + "\">" |
| + checkerName |
| + "</a> updated the check state to " |
| + CheckState.FAILED |
| + ".</p>" |
| + allChecksOverviewHtml( |
| ImmutableMap.of(CheckState.FAILED, ImmutableList.of(checkerName)))); |
| assertThat(message.htmlBody()).contains(GERRIT_MESSAGE_TYPE_COMBINED_CHECK_STATE_UPDATE); |
| } |
| |
| @Test |
| public void verifyMessageBodiesForCombinedCheckStateUpdatedToFailedEmailWithCheckMessage() |
| throws Exception { |
| String checkerName = "My Checker"; |
| CheckerUuid checkerUuid = |
| checkerOperations.newChecker().repository(project).name(checkerName).required().create(); |
| assertThat(getCombinedCheckState()).isEqualTo(CombinedCheckState.IN_PROGRESS); |
| |
| sender.clear(); |
| String checkMessage = "foo bar baz"; |
| postCheck(checkerUuid, CheckState.FAILED, checkMessage); |
| assertThat(getCombinedCheckState()).isEqualTo(CombinedCheckState.FAILED); |
| |
| List<Message> messages = sender.getMessages(); |
| assertThat(messages).hasSize(1); |
| |
| Message message = messages.get(0); |
| assertThat(message.body()) |
| .contains( |
| combinedCheckStateUpdatedText(CombinedCheckState.FAILED) |
| + "\n" |
| + "Checker " |
| + checkerName |
| + " updated the check state to " |
| + CheckState.FAILED |
| + ":\n" |
| + checkMessage |
| + "\n" |
| + allChecksOverviewText( |
| ImmutableMap.of(CheckState.FAILED, ImmutableList.of(checkerName)))); |
| assertThat(message.body()).contains(GERRIT_MESSAGE_TYPE_COMBINED_CHECK_STATE_UPDATE); |
| |
| assertThat(message.htmlBody()) |
| .contains( |
| combinedCheckStateUpdatedHtml(CombinedCheckState.FAILED) |
| + "<p>Checker <strong>" |
| + checkerName |
| + "</strong> updated the check state to " |
| + CheckState.FAILED |
| + ":<br>" |
| + checkMessage |
| + "</p>" |
| + allChecksOverviewHtml( |
| ImmutableMap.of(CheckState.FAILED, ImmutableList.of(checkerName)))); |
| assertThat(message.htmlBody()).contains(GERRIT_MESSAGE_TYPE_COMBINED_CHECK_STATE_UPDATE); |
| } |
| |
| @Test |
| public void verifyMessageBodiesForCombinedCheckStateUpdatedToFailedEmailWithCheckUrl() |
| throws Exception { |
| String checkerName = "My Checker"; |
| CheckerUuid checkerUuid = |
| checkerOperations.newChecker().repository(project).name(checkerName).required().create(); |
| assertThat(getCombinedCheckState()).isEqualTo(CombinedCheckState.IN_PROGRESS); |
| |
| sender.clear(); |
| String checkUrl = "http://my-checker/12345"; |
| postCheck(checkerUuid, CheckState.FAILED, null, checkUrl); |
| assertThat(getCombinedCheckState()).isEqualTo(CombinedCheckState.FAILED); |
| |
| List<Message> messages = sender.getMessages(); |
| assertThat(messages).hasSize(1); |
| |
| Message message = messages.get(0); |
| assertThat(message.body()) |
| .contains( |
| combinedCheckStateUpdatedText(CombinedCheckState.FAILED) |
| + "\n" |
| + "Checker " |
| + checkerName |
| + " updated the check state to " |
| + CheckState.FAILED |
| + " ( " |
| + checkUrl |
| + " ).\n" |
| + allChecksOverviewText( |
| ImmutableMap.of(CheckState.FAILED, ImmutableList.of(checkerName)))); |
| assertThat(message.body()).contains(GERRIT_MESSAGE_TYPE_COMBINED_CHECK_STATE_UPDATE); |
| |
| assertThat(message.htmlBody()) |
| .contains( |
| combinedCheckStateUpdatedHtml(CombinedCheckState.FAILED) |
| + "<p>Checker <strong>" |
| + checkerName |
| + "</strong> updated the check state to <a href=\"" |
| + checkUrl |
| + "\">" |
| + CheckState.FAILED |
| + "</a>.</p>" |
| + allChecksOverviewHtml( |
| ImmutableMap.of(CheckState.FAILED, ImmutableList.of(checkerName)), |
| ImmutableMap.of(checkerName, checkUrl))); |
| assertThat(message.htmlBody()).contains(GERRIT_MESSAGE_TYPE_COMBINED_CHECK_STATE_UPDATE); |
| } |
| |
| @Test |
| public void verifyMessageBodiesForCombinedCheckStateUpdatedToWarningEmail() throws Exception { |
| String checkerName = "My Checker"; |
| CheckerUuid checkerUuid = |
| checkerOperations.newChecker().repository(project).name(checkerName).create(); |
| assertThat(getCombinedCheckState()).isEqualTo(CombinedCheckState.IN_PROGRESS); |
| |
| sender.clear(); |
| postCheck(checkerUuid, CheckState.FAILED); |
| assertThat(getCombinedCheckState()).isEqualTo(CombinedCheckState.WARNING); |
| |
| List<Message> messages = sender.getMessages(); |
| assertThat(messages).hasSize(1); |
| |
| Message message = messages.get(0); |
| assertThat(message.body()) |
| .contains( |
| combinedCheckStateUpdatedText(CombinedCheckState.WARNING) |
| + "\n" |
| + "Checker " |
| + checkerName |
| + " updated the check state to " |
| + CheckState.FAILED |
| + ".\n" |
| + allChecksOverviewText( |
| ImmutableMap.of(CheckState.FAILED, ImmutableList.of(checkerName)))); |
| assertThat(message.body()).contains(GERRIT_MESSAGE_TYPE_COMBINED_CHECK_STATE_UPDATE); |
| |
| assertThat(message.htmlBody()) |
| .contains( |
| combinedCheckStateUpdatedHtml(CombinedCheckState.WARNING) |
| + "<p>Checker <strong>" |
| + checkerName |
| + "</strong> updated the check state to " |
| + CheckState.FAILED |
| + ".</p>" |
| + allChecksOverviewHtml( |
| ImmutableMap.of(CheckState.FAILED, ImmutableList.of(checkerName)))); |
| assertThat(message.htmlBody()).contains(GERRIT_MESSAGE_TYPE_COMBINED_CHECK_STATE_UPDATE); |
| } |
| |
| @Test |
| public void verifyMessageBodiesForCombinedCheckStateUpdatedToWarningFromFailedEmail() |
| throws Exception { |
| String checkerNameRequired = "My Required Checker"; |
| CheckerUuid checkerUuidRequired = |
| checkerOperations |
| .newChecker() |
| .name(checkerNameRequired) |
| .repository(project) |
| .required() |
| .create(); |
| postCheck(checkerUuidRequired, CheckState.FAILED); |
| |
| String checkerNameOptional = "My Optional Checker"; |
| CheckerUuid checkerUuidOptional = |
| checkerOperations.newChecker().name(checkerNameOptional).repository(project).create(); |
| postCheck(checkerUuidOptional, CheckState.FAILED); |
| assertThat(getCombinedCheckState()).isEqualTo(CombinedCheckState.FAILED); |
| |
| sender.clear(); |
| postCheck(checkerUuidRequired, CheckState.SUCCESSFUL); |
| assertThat(getCombinedCheckState()).isEqualTo(CombinedCheckState.WARNING); |
| |
| List<Message> messages = sender.getMessages(); |
| assertThat(messages).hasSize(1); |
| |
| Message message = messages.get(0); |
| assertThat(message.body()) |
| .contains( |
| combinedCheckStateUpdatedText(CombinedCheckState.WARNING) |
| + allChecksOverviewText( |
| ImmutableMap.of( |
| CheckState.SUCCESSFUL, |
| ImmutableList.of(checkerNameRequired), |
| CheckState.FAILED, |
| ImmutableList.of(checkerNameOptional)))); |
| assertThat(message.body()).contains(GERRIT_MESSAGE_TYPE_COMBINED_CHECK_STATE_UPDATE); |
| |
| assertThat(message.htmlBody()) |
| .contains( |
| combinedCheckStateUpdatedHtml(CombinedCheckState.WARNING) |
| + allChecksOverviewHtml( |
| ImmutableMap.of( |
| CheckState.SUCCESSFUL, |
| ImmutableList.of(checkerNameRequired), |
| CheckState.FAILED, |
| ImmutableList.of(checkerNameOptional)))); |
| assertThat(message.htmlBody()).contains(GERRIT_MESSAGE_TYPE_COMBINED_CHECK_STATE_UPDATE); |
| } |
| |
| @Test |
| public void verifyMessageBodiesForCombinedCheckStateUpdatedEmailWithBackfilledCheck() |
| throws Exception { |
| String checkerNameNotStartedBackfilled = "My Backfilled Checker"; |
| checkerOperations |
| .newChecker() |
| .name(checkerNameNotStartedBackfilled) |
| .repository(project) |
| .create(); |
| |
| String checkerNameFailed = "My Failed Checker"; |
| CheckerUuid checkerUuidFailed = |
| checkerOperations |
| .newChecker() |
| .name(checkerNameFailed) |
| .repository(project) |
| .required() |
| .create(); |
| |
| sender.clear(); |
| postCheck(checkerUuidFailed, CheckState.FAILED); |
| assertThat(getCombinedCheckState()).isEqualTo(CombinedCheckState.FAILED); |
| |
| List<Message> messages = sender.getMessages(); |
| assertThat(messages).hasSize(1); |
| |
| Map<CheckState, List<String>> expectedCheckersByState = new HashMap<>(); |
| expectedCheckersByState.put( |
| CheckState.NOT_STARTED, ImmutableList.of(checkerNameNotStartedBackfilled)); |
| expectedCheckersByState.put(CheckState.FAILED, ImmutableList.of(checkerNameFailed)); |
| |
| Message message = messages.get(0); |
| assertThat(message.body()) |
| .contains( |
| combinedCheckStateUpdatedText(CombinedCheckState.FAILED) |
| + "\n" |
| + "Checker " |
| + checkerNameFailed |
| + " updated the check state to " |
| + CheckState.FAILED |
| + ".\n" |
| + allChecksOverviewText(expectedCheckersByState)); |
| assertThat(message.body()).contains(GERRIT_MESSAGE_TYPE_COMBINED_CHECK_STATE_UPDATE); |
| |
| assertThat(message.htmlBody()) |
| .contains( |
| combinedCheckStateUpdatedHtml(CombinedCheckState.FAILED) |
| + "<p>Checker <strong>" |
| + checkerNameFailed |
| + "</strong> updated the check state to " |
| + CheckState.FAILED |
| + ".</p>" |
| + allChecksOverviewHtml(expectedCheckersByState)); |
| assertThat(message.htmlBody()).contains(GERRIT_MESSAGE_TYPE_COMBINED_CHECK_STATE_UPDATE); |
| } |
| |
| @Test |
| public void verifyMessageBodiesForCombinedCheckStateUpdatedEmailWithChecksOfDifferentStates() |
| throws Exception { |
| String checkerNameNotStarted = "My Not Started Checker"; |
| CheckerUuid checkerUuidNotStarted = |
| checkerOperations.newChecker().name(checkerNameNotStarted).repository(project).create(); |
| postCheck(checkerUuidNotStarted, CheckState.NOT_STARTED); |
| |
| String checkerNameScheduled = "My Scheduled Checker"; |
| CheckerUuid checkerUuidScheduled = |
| checkerOperations.newChecker().name(checkerNameScheduled).repository(project).create(); |
| postCheck(checkerUuidScheduled, CheckState.SCHEDULED); |
| |
| String checkerNameRunning = "My Running Checker"; |
| CheckerUuid checkerUuidRunning = |
| checkerOperations.newChecker().name(checkerNameRunning).repository(project).create(); |
| postCheck(checkerUuidRunning, CheckState.RUNNING); |
| |
| String checkerNameNotRelevant = "My Not Relevant Checker"; |
| CheckerUuid checkerUuidNotRelevant = |
| checkerOperations.newChecker().name(checkerNameNotRelevant).repository(project).create(); |
| postCheck(checkerUuidNotRelevant, CheckState.NOT_RELEVANT); |
| |
| String checkerNameSuccesful = "My Successful Checker"; |
| CheckerUuid checkerUuidSuccessful = |
| checkerOperations.newChecker().name(checkerNameSuccesful).repository(project).create(); |
| postCheck(checkerUuidSuccessful, CheckState.SUCCESSFUL); |
| |
| String checkerNameFailed = "My Failed Checker"; |
| CheckerUuid checkerUuidFailed = |
| checkerOperations |
| .newChecker() |
| .name(checkerNameFailed) |
| .repository(project) |
| .required() |
| .create(); |
| |
| sender.clear(); |
| postCheck(checkerUuidFailed, CheckState.FAILED); |
| assertThat(getCombinedCheckState()).isEqualTo(CombinedCheckState.FAILED); |
| |
| List<Message> messages = sender.getMessages(); |
| assertThat(messages).hasSize(1); |
| |
| Map<CheckState, List<String>> expectedCheckersByState = new HashMap<>(); |
| expectedCheckersByState.put(CheckState.NOT_STARTED, ImmutableList.of(checkerNameNotStarted)); |
| expectedCheckersByState.put(CheckState.SCHEDULED, ImmutableList.of(checkerNameScheduled)); |
| expectedCheckersByState.put(CheckState.RUNNING, ImmutableList.of(checkerNameRunning)); |
| expectedCheckersByState.put(CheckState.NOT_RELEVANT, ImmutableList.of(checkerNameNotRelevant)); |
| expectedCheckersByState.put(CheckState.SUCCESSFUL, ImmutableList.of(checkerNameSuccesful)); |
| expectedCheckersByState.put(CheckState.FAILED, ImmutableList.of(checkerNameFailed)); |
| |
| Message message = messages.get(0); |
| assertThat(message.body()) |
| .contains( |
| combinedCheckStateUpdatedText(CombinedCheckState.FAILED) |
| + "\n" |
| + "Checker " |
| + checkerNameFailed |
| + " updated the check state to " |
| + CheckState.FAILED |
| + ".\n" |
| + allChecksOverviewText(expectedCheckersByState)); |
| assertThat(message.body()).contains(GERRIT_MESSAGE_TYPE_COMBINED_CHECK_STATE_UPDATE); |
| |
| assertThat(message.htmlBody()) |
| .contains( |
| combinedCheckStateUpdatedHtml(CombinedCheckState.FAILED) |
| + "<p>Checker <strong>" |
| + checkerNameFailed |
| + "</strong> updated the check state to " |
| + CheckState.FAILED |
| + ".</p>" |
| + allChecksOverviewHtml(expectedCheckersByState)); |
| assertThat(message.htmlBody()).contains(GERRIT_MESSAGE_TYPE_COMBINED_CHECK_STATE_UPDATE); |
| } |
| |
| @Test |
| public void verifyMessageBodiesForCombinedCheckStateUpdatedEmailWithMultipleChecksOfSameState() |
| throws Exception { |
| String checkerNameRunningFoo = "Foo Checker"; |
| CheckerUuid checkerUuidRunningFoo = |
| checkerOperations.newChecker().name(checkerNameRunningFoo).repository(project).create(); |
| String checkUrlFoo = "http://foo-checker/12345"; |
| postCheck(checkerUuidRunningFoo, CheckState.RUNNING, null, checkUrlFoo); |
| |
| String checkerNameRunningBar = "Bar Checker"; |
| CheckerUuid checkerUuidRunningBar = |
| checkerOperations.newChecker().name(checkerNameRunningBar).repository(project).create(); |
| String checkUrlBar = "http://bar-checker/67890"; |
| postCheck(checkerUuidRunningBar, CheckState.RUNNING, null, checkUrlBar); |
| |
| String checkerNameRunningBaz = "Baz Checker"; |
| CheckerUuid checkerUuidRunningBaz = |
| checkerOperations.newChecker().name(checkerNameRunningBaz).repository(project).create(); |
| // This check doesn't have an URL, so that we test a mix of checks with and without URL. |
| postCheck(checkerUuidRunningBaz, CheckState.RUNNING); |
| |
| String checkerNameFailed = "My Failed Checker"; |
| CheckerUuid checkerUuidFailed = |
| checkerOperations |
| .newChecker() |
| .name(checkerNameFailed) |
| .repository(project) |
| .required() |
| .create(); |
| |
| sender.clear(); |
| postCheck(checkerUuidFailed, CheckState.FAILED); |
| assertThat(getCombinedCheckState()).isEqualTo(CombinedCheckState.FAILED); |
| |
| List<Message> messages = sender.getMessages(); |
| assertThat(messages).hasSize(1); |
| |
| Map<CheckState, List<String>> expectedCheckersByState = new HashMap<>(); |
| expectedCheckersByState.put( |
| CheckState.RUNNING, |
| ImmutableList.of(checkerNameRunningBar, checkerNameRunningBaz, checkerNameRunningFoo)); |
| expectedCheckersByState.put(CheckState.FAILED, ImmutableList.of(checkerNameFailed)); |
| |
| Message message = messages.get(0); |
| assertThat(message.body()) |
| .contains( |
| combinedCheckStateUpdatedText(CombinedCheckState.FAILED) |
| + "\n" |
| + "Checker " |
| + checkerNameFailed |
| + " updated the check state to " |
| + CheckState.FAILED |
| + ".\n" |
| + allChecksOverviewText(expectedCheckersByState)); |
| assertThat(message.body()).contains(GERRIT_MESSAGE_TYPE_COMBINED_CHECK_STATE_UPDATE); |
| |
| assertThat(message.htmlBody()) |
| .contains( |
| combinedCheckStateUpdatedHtml(CombinedCheckState.FAILED) |
| + "<p>Checker <strong>" |
| + checkerNameFailed |
| + "</strong> updated the check state to " |
| + CheckState.FAILED |
| + ".</p>" |
| + allChecksOverviewHtml( |
| expectedCheckersByState, |
| ImmutableMap.of( |
| checkerNameRunningFoo, checkUrlFoo, checkerNameRunningBar, checkUrlBar))); |
| assertThat(message.htmlBody()).contains(GERRIT_MESSAGE_TYPE_COMBINED_CHECK_STATE_UPDATE); |
| } |
| |
| @Test |
| public void noEmailForCombinedCheckStateUpdatesOfNonCurrentPatchSet() throws Exception { |
| CheckerUuid checkerUuid = |
| checkerOperations.newChecker().name("My Checker").repository(project).create(); |
| |
| // push a new patch set |
| PushOneCommit push = |
| pushFactory.create( |
| admin.newIdent(), |
| testRepo, |
| PushOneCommit.SUBJECT, |
| PushOneCommit.FILE_NAME, |
| "new content " + System.nanoTime(), |
| change.getKey().get()); |
| push.to("refs/for/master").assertOkStatus(); |
| |
| sender.clear(); |
| |
| // post check on old patch set |
| postCheck(checkerUuid, CheckState.SUCCESSFUL); |
| |
| assertThat(sender.getMessages()).isEmpty(); |
| } |
| |
| private String combinedCheckStateUpdatedText(CombinedCheckState combinedCheckState) { |
| return "The combined check state has been updated to " |
| + combinedCheckState |
| + " for patch set " |
| + patchSetId.get() |
| + " of this change ( " |
| + changeUrl(change) |
| + " ).\n"; |
| } |
| |
| private String allChecksOverviewText(Map<CheckState, List<String>> checkersByState) { |
| StringBuilder b = new StringBuilder(); |
| b.append("\nAll checks:\n"); |
| if (checkersByState.containsKey(CheckState.SUCCESSFUL)) { |
| b.append("Successful: ") |
| .append(Joiner.on(", ").join(checkersByState.get(CheckState.SUCCESSFUL))) |
| .append("\n"); |
| } |
| if (checkersByState.containsKey(CheckState.NOT_RELEVANT)) { |
| b.append("Not Relevant: ") |
| .append(Joiner.on(", ").join(checkersByState.get(CheckState.NOT_RELEVANT))) |
| .append("\n"); |
| } |
| if (checkersByState.containsKey(CheckState.FAILED)) { |
| b.append("Failed: ") |
| .append(Joiner.on(", ").join(checkersByState.get(CheckState.FAILED))) |
| .append("\n"); |
| } |
| if (checkersByState.containsKey(CheckState.RUNNING)) { |
| b.append("Running: ") |
| .append(Joiner.on(", ").join(checkersByState.get(CheckState.RUNNING))) |
| .append("\n"); |
| } |
| if (checkersByState.containsKey(CheckState.SCHEDULED)) { |
| b.append("Scheduled: ") |
| .append(Joiner.on(", ").join(checkersByState.get(CheckState.SCHEDULED))) |
| .append("\n"); |
| } |
| if (checkersByState.containsKey(CheckState.NOT_STARTED)) { |
| b.append("Not Started: ") |
| .append(Joiner.on(", ").join(checkersByState.get(CheckState.NOT_STARTED))) |
| .append("\n"); |
| } |
| return b.toString(); |
| } |
| |
| private String combinedCheckStateUpdatedHtml(CombinedCheckState combinedCheckState) { |
| return "<p>The combined check state has been updated to <strong>" |
| + combinedCheckState |
| + "</strong> for patch set " |
| + patchSetId.get() |
| + " of this <a href=\"" |
| + changeUrl(change) |
| + "\">change</a>.</p>"; |
| } |
| |
| private String allChecksOverviewHtml(Map<CheckState, List<String>> checkersByState) { |
| return allChecksOverviewHtml(checkersByState, ImmutableMap.of()); |
| } |
| |
| private String allChecksOverviewHtml( |
| Map<CheckState, List<String>> checkersByState, Map<String, String> urlsByChecker) { |
| Map<CheckState, List<String>> checkersByStateFormatted = |
| checkersByState.entrySet().stream() |
| .collect( |
| toMap( |
| e -> e.getKey(), |
| e -> |
| e.getValue().stream() |
| .map( |
| c -> |
| urlsByChecker.containsKey(c) |
| ? "<a href=\"" + urlsByChecker.get(c) + "\">" + c + "</a>" |
| : c) |
| .collect(toList()))); |
| |
| StringBuilder b = new StringBuilder(); |
| b.append("<p><u><strong>All checks:</strong></u><br>"); |
| if (checkersByState.containsKey(CheckState.SUCCESSFUL)) { |
| b.append("<strong>Successful:</strong> ") |
| .append(Joiner.on(", ").join(checkersByStateFormatted.get(CheckState.SUCCESSFUL))) |
| .append("<br>"); |
| } |
| if (checkersByState.containsKey(CheckState.NOT_RELEVANT)) { |
| b.append("<strong>Not Relevant:</strong> ") |
| .append(Joiner.on(", ").join(checkersByStateFormatted.get(CheckState.NOT_RELEVANT))) |
| .append("<br>"); |
| } |
| if (checkersByState.containsKey(CheckState.FAILED)) { |
| b.append("<strong>Failed:</strong> ") |
| .append(Joiner.on(", ").join(checkersByStateFormatted.get(CheckState.FAILED))) |
| .append("<br>"); |
| } |
| if (checkersByState.containsKey(CheckState.RUNNING)) { |
| b.append("<strong>Running:</strong> ") |
| .append(Joiner.on(", ").join(checkersByStateFormatted.get(CheckState.RUNNING))) |
| .append("<br>"); |
| } |
| if (checkersByState.containsKey(CheckState.SCHEDULED)) { |
| b.append("<strong>Scheduled:</strong> ") |
| .append(Joiner.on(", ").join(checkersByStateFormatted.get(CheckState.SCHEDULED))) |
| .append("<br>"); |
| } |
| if (checkersByState.containsKey(CheckState.NOT_STARTED)) { |
| b.append("<strong>Not Started:</strong> ") |
| .append(Joiner.on(", ").join(checkersByStateFormatted.get(CheckState.NOT_STARTED))) |
| .append("<br>"); |
| } |
| b.append("</p>"); |
| return b.toString(); |
| } |
| |
| private String htmlViewChangeButton() { |
| return "<p><a href=\"" + changeUrl(change) + "\">View Change</a></p>"; |
| } |
| |
| private String changeUrl(Change change) { |
| return canonicalWebUrl.get() + "c/" + change.getProject().get() + "/+/" + change.getChangeId(); |
| } |
| |
| private CombinedCheckState getCombinedCheckState() throws RestApiException { |
| ChangeInfo changeInfo = |
| gApi.changes() |
| .id(patchSetId.changeId().get()) |
| .get(ImmutableListMultimap.of("checks--combined", "true")); |
| ImmutableList<PluginDefinedInfo> infos = |
| changeInfo.plugins.stream().filter(i -> i.name.equals("checks")).collect(toImmutableList()); |
| assertThat(infos).hasSize(1); |
| assertThat(infos.get(0)).isInstanceOf(ChangeCheckInfo.class); |
| return ((ChangeCheckInfo) infos.get(0)).combinedState; |
| } |
| |
| private void postCheck(CheckerUuid checkerUuid, CheckState checkState) throws RestApiException { |
| postCheck(checkerUuid, checkState, null); |
| } |
| |
| private void postCheck(CheckerUuid checkerUuid, CheckState checkState, @Nullable String message) |
| throws RestApiException { |
| postCheck(checkerUuid, checkState, message, null); |
| } |
| |
| private void postCheck( |
| CheckerUuid checkerUuid, |
| CheckState checkState, |
| @Nullable String message, |
| @Nullable String url) |
| throws RestApiException { |
| requestScopeOperations.setApiUser(bot.id()); |
| CheckInput input = new CheckInput(); |
| input.checkerUuid = checkerUuid.get(); |
| input.state = checkState; |
| input.message = message; |
| input.url = url; |
| checksApiFactory.revision(patchSetId).create(input).get(); |
| } |
| } |