// 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.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 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));

    // 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 Exception {
    testNotifySettingsForPostCheck(checkerUuid, ImmutableSet.of(), notify, expectedRecipients);
  }

  private void testNotifySettingsForPostCheck(
      CheckerUuid checkerUuid,
      Set<TestAccount> accountsToNotify,
      NotifyHandling notify,
      TestAccount... expectedRecipients)
      throws Exception {
    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 Exception {
    testNotifySettingsForPostCheck(checkerUuid, ImmutableSet.of(), notify, expectedRecipients);
  }

  private void testNotifySettingsForRerunCheck(
      CheckerUuid checkerUuid,
      Set<TestAccount> accountsToNotify,
      NotifyHandling notify,
      TestAccount... expectedRecipients)
      throws Exception {
    // 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()
        + "?usp=email";
  }

  private CombinedCheckState getCombinedCheckState() throws Exception {
    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 Exception {
    postCheck(checkerUuid, checkState, null);
  }

  private void postCheck(CheckerUuid checkerUuid, CheckState checkState, @Nullable String message)
      throws Exception {
    postCheck(checkerUuid, checkState, message, null);
  }

  private void postCheck(
      CheckerUuid checkerUuid,
      CheckState checkState,
      @Nullable String message,
      @Nullable String url)
      throws Exception {
    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();
  }
}
