// 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.truth.Truth.assertThat;
import static com.google.gerrit.acceptance.testsuite.project.TestProjectUpdate.allow;
import static com.google.gerrit.acceptance.testsuite.project.TestProjectUpdate.block;
import static com.google.gerrit.plugins.checks.testing.PendingChecksInfoSubject.assertThat;
import static com.google.gerrit.server.group.SystemGroupBackend.REGISTERED_USERS;
import static com.google.gerrit.testing.GerritJUnit.assertThrows;

import com.google.common.collect.Iterables;
import com.google.gerrit.acceptance.RestResponse;
import com.google.gerrit.acceptance.UseClockStep;
import com.google.gerrit.acceptance.testsuite.project.ProjectOperations;
import com.google.gerrit.acceptance.testsuite.request.RequestScopeOperations;
import com.google.gerrit.common.data.Permission;
import com.google.gerrit.entities.PatchSet;
import com.google.gerrit.extensions.restapi.BadRequestException;
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.acceptance.testsuite.CheckerTestData;
import com.google.gerrit.plugins.checks.api.CheckState;
import com.google.gerrit.plugins.checks.api.PendingCheckInfo;
import com.google.gerrit.plugins.checks.api.PendingChecksInfo;
import com.google.gson.reflect.TypeToken;
import com.google.inject.Inject;
import java.util.List;
import java.util.StringJoiner;
import java.util.stream.Stream;
import org.eclipse.jgit.errors.ConfigInvalidException;
import org.junit.Before;
import org.junit.Test;

@UseClockStep(startAtEpoch = true)
public class QueryPendingChecksIT extends AbstractCheckersTest {
  @Inject private ProjectOperations projectOperations;
  @Inject private RequestScopeOperations requestScopeOperations;

  private PatchSet.Id patchSetId;

  @Before
  public void setUp() throws Exception {
    patchSetId = createChange().getPatchSetId();
  }

  @Test
  public void specifyingQueryIsRequired() throws Exception {
    assertInvalidQuery(null, "query is required");
  }

  @Test
  public void queryCannotBeEmpty() throws Exception {
    assertInvalidQuery("", "query is empty");
  }

  @Test
  public void queryCannotBeEmptyAfterTrim() throws Exception {
    assertInvalidQuery(" ", "query is empty");
  }

  @Test
  public void specifyingCheckerOrSchemeIsRequired() throws Exception {
    assertInvalidQuery(
        "state:NOT_STARTED",
        "query must contain exactly 1 'checker' operator or 'scheme' operator");
  }

  @Test
  public void cannotQueryPendingChecksForInvalidCheckerUuid() throws Exception {
    assertInvalidQuery(
        "checker:" + CheckerTestData.INVALID_UUID,
        "invalid checker UUID: " + CheckerTestData.INVALID_UUID);
  }

  @Test
  public void cannotSpecifyMultipleCheckers() throws Exception {
    CheckerUuid checkerUuid1 = checkerOperations.newChecker().repository(project).create();
    CheckerUuid checkerUuid2 = checkerOperations.newChecker().repository(project).create();

    String expectedMessage = "query must contain exactly 1 'checker' operator or 'scheme' operator";
    assertInvalidQuery(
        String.format("checker:\"%s\" checker:\"%s\"", checkerUuid1, checkerUuid2),
        expectedMessage);
    assertInvalidQuery(
        String.format("checker:\"%s\" OR checker:\"%s\"", checkerUuid1, checkerUuid2),
        expectedMessage);
    assertInvalidQuery(
        String.format(
            "checker:\"%s\" (state:NOT_STARTED checker:\"%s\")", checkerUuid1, checkerUuid2),
        expectedMessage);
  }

  @Test
  public void cannotSpecifyMultipleSchemes() throws Exception {
    CheckerUuid checkerUuid1 = checkerOperations.newChecker().repository(project).create();
    CheckerUuid checkerUuid2 = checkerOperations.newChecker().repository(project).create();

    String expectedMessage = "query must contain exactly 1 'checker' operator or 'scheme' operator";
    assertInvalidQuery(
        String.format("scheme:\"%s\" scheme:\"%s\"", checkerUuid1.scheme(), checkerUuid2.scheme()),
        expectedMessage);
    assertInvalidQuery(
        String.format(
            "scheme:\"%s\" OR scheme:\"%s\"", checkerUuid1.scheme(), checkerUuid2.scheme()),
        expectedMessage);
    assertInvalidQuery(
        String.format(
            "scheme:\"%s\" (state:NOT_STARTED scheme:\"%s\")",
            checkerUuid1.scheme(), checkerUuid2.scheme()),
        expectedMessage);
  }

  @Test
  public void canSpecifyCheckerAsRootPredicate() throws Exception {
    CheckerUuid checkerUuid = checkerOperations.newChecker().repository(project).create();
    assertThat(queryPendingChecks(String.format("checker:\"%s\"", checkerUuid))).hasSize(1);
  }

  @Test
  public void canSpecifyCheckerInAndCondition() throws Exception {
    CheckerUuid checkerUuid = checkerOperations.newChecker().repository(project).create();
    assertThat(
            queryPendingChecks(String.format("checker:\"%s\" AND state:NOT_STARTED", checkerUuid)))
        .hasSize(1);
  }

  @Test
  public void cannotSpecifyCheckerInAndConditionIfNotImmediateChild() throws Exception {
    CheckerUuid checkerUuid = checkerOperations.newChecker().repository(project).create();

    String expectedMessage =
        "query must be 'checker:<checker-uuid>' or 'checker:<checker-uuid> AND <other-operators>' or 'scheme:<checker-scheme>' or 'scheme:<checker-scheme> AND <other-operators>'";
    assertInvalidQuery(
        String.format("state:NOT_STARTED AND (checker:\"%s\" OR state:NOT_STARTED)", checkerUuid),
        expectedMessage);
    assertInvalidQuery(
        String.format("state:NOT_STARTED AND NOT checker:\"%s\"", checkerUuid), expectedMessage);
  }

  @Test
  public void cannotSpecifySchemeInAndConditionIfNotImmediateChild() throws Exception {
    CheckerUuid checkerUuid = checkerOperations.newChecker().repository(project).create();

    String expectedMessage =
        "query must be 'checker:<checker-uuid>' or 'checker:<checker-uuid> AND <other-operators>' or 'scheme:<checker-scheme>' or 'scheme:<checker-scheme> AND <other-operators>'";
    assertInvalidQuery(
        String.format(
            "state:NOT_STARTED AND (scheme:\"%s\" OR state:NOT_STARTED)", checkerUuid.scheme()),
        expectedMessage);
    assertInvalidQuery(
        String.format("state:NOT_STARTED AND NOT scheme:\"%s\"", checkerUuid.scheme()),
        expectedMessage);
  }

  @Test
  public void andConditionAtRootCanContainAnyCombinationOfOtherPredicates() throws Exception {
    CheckerUuid checkerUuid = checkerOperations.newChecker().repository(project).create();

    assertThat(
            queryPendingChecks(
                String.format(
                    "checker:\"%s\" AND (state:NOT_STARTED OR state:RUNNING)", checkerUuid)))
        .hasSize(1);
    assertThat(
            queryPendingChecks(
                String.format("checker:\"%s\" AND NOT state:NOT_STARTED)", checkerUuid)))
        .isEmpty();
    assertThat(
            queryPendingChecks(
                String.format(
                    "checker:\"%s\" AND (NOT state:FAILED AND NOT (state:RUNNING OR"
                        + " state:SUCCESSFUL))",
                    checkerUuid)))
        .hasSize(1);
  }

  @Test
  public void cannotSpecifyCheckerInOrCondition() throws Exception {
    CheckerUuid checkerUuid = checkerOperations.newChecker().repository(project).create();

    String expectedMessage =
        "query must be 'checker:<checker-uuid>' or 'checker:<checker-uuid> AND <other-operators>' or 'scheme:<checker-scheme>' or 'scheme:<checker-scheme> AND <other-operators>'";
    assertInvalidQuery(
        String.format("checker:\"%s\" OR state:NOT_STARTED", checkerUuid), expectedMessage);
    assertInvalidQuery(
        String.format("state:NOT_STARTED OR checker:\"%s\"", checkerUuid), expectedMessage);
  }

  @Test
  public void cannotSpecifySchemeInOrCondition() throws Exception {
    CheckerUuid checkerUuid = checkerOperations.newChecker().repository(project).create();

    String expectedMessage =
        "query must be 'checker:<checker-uuid>' or 'checker:<checker-uuid> AND <other-operators>' or 'scheme:<checker-scheme>' or 'scheme:<checker-scheme> AND <other-operators>'";
    assertInvalidQuery(
        String.format("scheme:\"%s\" OR state:NOT_STARTED", checkerUuid.scheme()), expectedMessage);
    assertInvalidQuery(
        String.format("state:NOT_STARTED OR scheme:\"%s\"", checkerUuid.scheme()), expectedMessage);
  }

  @Test
  public void cannotSpecifyCheckerInNotCondition() throws Exception {
    CheckerUuid checkerUuid = checkerOperations.newChecker().repository(project).create();
    assertInvalidQuery(
        String.format("NOT checker:\"%s\"", checkerUuid),
        "query must be 'checker:<checker-uuid>' or 'checker:<checker-uuid> AND <other-operators>' or 'scheme:<checker-scheme>' or 'scheme:<checker-scheme> AND <other-operators>'");
  }

  @Test
  public void cannotSpecifySchemeInNotCondition() throws Exception {
    CheckerUuid checkerUuid = checkerOperations.newChecker().repository(project).create();
    assertInvalidQuery(
        String.format("NOT scheme:\"%s\"", checkerUuid.scheme()),
        "query must be 'checker:<checker-uuid>' or 'checker:<checker-uuid> AND <other-operators>' or 'scheme:<checker-scheme>' or 'scheme:<checker-scheme> AND <other-operators>'");
  }

  @Test
  public void queryPendingChecksForNonExistingChecker() throws Exception {
    assertThat(pendingChecksApi.query("checker:\"non:existing\"").get()).isEmpty();
  }

  @Test
  public void queryPendingChecksNotStartedStateAssumed() throws Exception {
    CheckerUuid checkerUuid = checkerOperations.newChecker().repository(project).create();

    // Create a check with state "NOT_STARTED" that we expect to be returned.
    checkOperations
        .newCheck(CheckKey.create(project, patchSetId, checkerUuid))
        .state(CheckState.NOT_STARTED)
        .upsert();

    // Create a check with state "FAILED" that we expect to be ignored.
    PatchSet.Id patchSetId2 = createChange().getPatchSetId();
    checkOperations
        .newCheck(CheckKey.create(project, patchSetId2, checkerUuid))
        .state(CheckState.FAILED)
        .upsert();

    // Create a check with state "NOT_STARTED" for other checker that we expect to be ignored.
    CheckerUuid checkerUuid2 = checkerOperations.newChecker().repository(project).create();
    checkOperations
        .newCheck(CheckKey.create(project, patchSetId, checkerUuid2))
        .state(CheckState.NOT_STARTED)
        .upsert();

    List<PendingChecksInfo> pendingChecksList = queryPendingChecks(checkerUuid);
    assertThat(pendingChecksList).hasSize(1);
    PendingChecksInfo pendingChecks = Iterables.getOnlyElement(pendingChecksList);
    assertThat(pendingChecks).hasRepository(project);
    assertThat(pendingChecks).hasPatchSet(patchSetId);
    assertThat(pendingChecks)
        .hasPendingChecksMapThat()
        .containsExactly(checkerUuid.get(), new PendingCheckInfo(CheckState.NOT_STARTED));
  }

  @Test
  public void queryPendingChecksForSpecifiedState() throws Exception {
    CheckerUuid checkerUuid = checkerOperations.newChecker().repository(project).create();

    // Create a check with state "FAILED" that we expect to be returned.
    checkOperations
        .newCheck(CheckKey.create(project, patchSetId, checkerUuid))
        .state(CheckState.FAILED)
        .upsert();

    // Create a check with state "NOT_STARTED" that we expect to be ignored.
    PatchSet.Id patchSetId2 = createChange().getPatchSetId();
    checkOperations
        .newCheck(CheckKey.create(project, patchSetId2, checkerUuid))
        .state(CheckState.NOT_STARTED)
        .upsert();

    // Create a check with state "FAILED" for other checker that we expect to be ignored.
    CheckerUuid checkerUuid2 = checkerOperations.newChecker().repository(project).create();
    checkOperations
        .newCheck(CheckKey.create(project, patchSetId, checkerUuid2))
        .state(CheckState.FAILED)
        .upsert();

    List<PendingChecksInfo> pendingChecksList = queryPendingChecks(checkerUuid, CheckState.FAILED);
    assertThat(pendingChecksList).hasSize(1);
    PendingChecksInfo pendingChecks = Iterables.getOnlyElement(pendingChecksList);
    assertThat(pendingChecks).hasRepository(project);
    assertThat(pendingChecks).hasPatchSet(patchSetId);
    assertThat(pendingChecks)
        .hasPendingChecksMapThat()
        .containsExactly(checkerUuid.get(), new PendingCheckInfo(CheckState.FAILED));
  }

  @Test
  public void queryPendingChecksForSpecifiedStateByIsOperator() throws Exception {
    CheckerUuid checkerUuid = checkerOperations.newChecker().repository(project).create();

    // Create the check once so that in the for-loop we can always update an existing check, rather
    // than needing to check if the check already exists and then depending on this either create or
    // update it.
    checkOperations
        .newCheck(CheckKey.create(project, patchSetId, checkerUuid))
        .state(CheckState.NOT_STARTED)
        .upsert();

    for (CheckState checkState : CheckState.values()) {
      checkOperations
          .check(CheckKey.create(project, patchSetId, checkerUuid))
          .forUpdate()
          .state(checkState)
          .upsert();

      assertThat(queryPendingChecks(String.format("checker:\"%s\" is:%s", checkerUuid, checkState)))
          .hasSize(1);
    }
  }

  @Test
  public void queryPendingChecksByIsInprogressOperator() throws Exception {
    CheckerUuid checkerUuid = checkerOperations.newChecker().repository(project).create();

    // Create the check once so that in the for-loop we can always update an existing check, rather
    // than needing to check if the check already exists and then depending on this either create or
    // update it.
    checkOperations
        .newCheck(CheckKey.create(project, patchSetId, checkerUuid))
        .state(CheckState.NOT_STARTED)
        .upsert();

    for (CheckState checkState : CheckState.values()) {
      checkOperations
          .check(CheckKey.create(project, patchSetId, checkerUuid))
          .forUpdate()
          .state(checkState)
          .upsert();

      List<PendingChecksInfo> pendingChecks =
          queryPendingChecks(String.format("checker:\"%s\" is:inprogress", checkerUuid));
      if (checkState.isInProgress()) {
        assertThat(pendingChecks).hasSize(1);
      } else {
        assertThat(pendingChecks).isEmpty();
      }

      pendingChecks =
          queryPendingChecks(String.format("checker:\"%s\" is:in_progress", checkerUuid));
      if (checkState.isInProgress()) {
        assertThat(pendingChecks).hasSize(1);
      } else {
        assertThat(pendingChecks).isEmpty();
      }
    }
  }

  @Test
  public void invalidStateInIsOperatorIsRejected() throws Exception {
    CheckerUuid checkerUuid = checkerOperations.newChecker().repository(project).create();
    assertInvalidQuery(
        String.format("checker:%s is:foo", checkerUuid), "unsupported operator: is:foo");
  }

  @Test
  public void queryPendingChecksForMultipleSpecifiedStates() throws Exception {
    CheckerUuid checkerUuid = checkerOperations.newChecker().repository(project).create();

    // Create a check with state "NOT_STARTED" that we expect to be returned.
    checkOperations
        .newCheck(CheckKey.create(project, patchSetId, checkerUuid))
        .state(CheckState.NOT_STARTED)
        .upsert();

    // Create a check with state "SCHEDULED" that we expect to be returned.
    PatchSet.Id patchSetId2 = createChange().getPatchSetId();
    checkOperations
        .newCheck(CheckKey.create(project, patchSetId2, checkerUuid))
        .state(CheckState.SCHEDULED)
        .upsert();

    // Create a check with state "SUCCESSFUL" that we expect to be ignored.
    PatchSet.Id patchSetId3 = createChange().getPatchSetId();
    checkOperations
        .newCheck(CheckKey.create(project, patchSetId3, checkerUuid))
        .state(CheckState.SUCCESSFUL)
        .upsert();

    // Create a check with state "NOT_STARTED" for other checker that we expect to be ignored.
    CheckerUuid checkerUuid2 = checkerOperations.newChecker().repository(project).create();
    checkOperations
        .newCheck(CheckKey.create(project, patchSetId, checkerUuid2))
        .state(CheckState.NOT_STARTED)
        .upsert();

    List<PendingChecksInfo> pendingChecksList =
        queryPendingChecks(checkerUuid, CheckState.NOT_STARTED, CheckState.SCHEDULED);
    assertThat(pendingChecksList).hasSize(2);

    // The sorting of the pendingChecksList matches the sorting in which the matching changes are
    // returned from the change index, which is by last updated timestamp. Use this knowledge here
    // to do the assertions although the REST endpoint doesn't document a guaranteed sort order.
    PendingChecksInfo pendingChecksChange2 = pendingChecksList.get(0);
    assertThat(pendingChecksChange2).hasRepository(project);
    assertThat(pendingChecksChange2).hasPatchSet(patchSetId2);
    assertThat(pendingChecksChange2)
        .hasPendingChecksMapThat()
        .containsExactly(checkerUuid.get(), new PendingCheckInfo(CheckState.SCHEDULED));

    PendingChecksInfo pendingChecksChange1 = pendingChecksList.get(1);
    assertThat(pendingChecksChange1).hasRepository(project);
    assertThat(pendingChecksChange1).hasPatchSet(patchSetId);
    assertThat(pendingChecksChange1)
        .hasPendingChecksMapThat()
        .containsExactly(checkerUuid.get(), new PendingCheckInfo(CheckState.NOT_STARTED));
  }

  @Test
  public void queryPendingChecksForSpecifiedStateUnderscoreCanBeOmitted() throws Exception {
    CheckerUuid checkerUuid = checkerOperations.newChecker().repository(project).create();

    // Create the check once so that in the for-loop we can always update an existing check, rather
    // than needing to check if the check already exists and then depending on this either create or
    // update it.
    checkOperations
        .newCheck(CheckKey.create(project, patchSetId, checkerUuid))
        .state(CheckState.NOT_STARTED)
        .upsert();

    for (CheckState checkState : CheckState.values()) {
      checkOperations
          .check(CheckKey.create(project, patchSetId, checkerUuid))
          .forUpdate()
          .state(checkState)
          .upsert();

      List<PendingChecksInfo> pendingChecks =
          queryPendingChecks(
              String.format(
                  "checker:\"%s\" is:%s", checkerUuid, checkState.name().replace("_", "")));
      assertThat(pendingChecks).hasSize(1);
    }
  }

  @Test
  public void queryPendingChecksForSpecifiedStateDifferentCases() throws Exception {
    CheckerUuid checkerUuid = checkerOperations.newChecker().repository(project).create();

    assertThat(queryPendingChecks(buildQueryString(checkerUuid) + " state:NOT_STARTED")).hasSize(1);
    assertThat(queryPendingChecks(buildQueryString(checkerUuid) + " state:not_started")).hasSize(1);
    assertThat(queryPendingChecks(buildQueryString(checkerUuid) + " state:NoT_StArTeD")).hasSize(1);
    assertThat(queryPendingChecks(buildQueryString(checkerUuid) + " state:NOTSTARTED")).hasSize(1);
    assertThat(queryPendingChecks(buildQueryString(checkerUuid) + " state:notstarted")).hasSize(1);
    assertThat(queryPendingChecks(buildQueryString(checkerUuid) + " state:NoTStArTeD")).hasSize(1);
  }

  @Test
  public void backfillForApplyingChecker() throws Exception {
    CheckerUuid checkerUuid = checkerOperations.newChecker().repository(project).create();
    List<PendingChecksInfo> pendingChecksList = queryPendingChecks(checkerUuid);
    assertThat(pendingChecksList).hasSize(1);
    PendingChecksInfo pendingChecks = Iterables.getOnlyElement(pendingChecksList);
    assertThat(pendingChecks).hasRepository(project);
    assertThat(pendingChecks).hasPatchSet(patchSetId);
    assertThat(pendingChecks)
        .hasPendingChecksMapThat()
        .containsExactly(checkerUuid.get(), new PendingCheckInfo(CheckState.NOT_STARTED));
  }

  @Test
  public void noBackfillForCheckerThatDoesNotApplyToTheProject() throws Exception {
    CheckerUuid checkerUuid = checkerOperations.newChecker().repository(allProjects).create();
    assertThat(queryPendingChecks(checkerUuid)).isEmpty();
  }

  @Test
  public void noBackfillForCheckerThatDoesNotApplyToTheChange() throws Exception {
    CheckerUuid checkerUuid =
        checkerOperations.newChecker().repository(project).query("message:not-matching").create();
    assertThat(queryPendingChecks(checkerUuid)).isEmpty();
  }

  @Test
  public void queryPendingChecksForDisabledChecker() throws Exception {
    CheckerUuid checkerUuid = checkerOperations.newChecker().repository(project).create();
    checkOperations
        .newCheck(CheckKey.create(project, patchSetId, checkerUuid))
        .state(CheckState.NOT_STARTED)
        .upsert();

    List<PendingChecksInfo> pendingChecksList =
        queryPendingChecks(checkerUuid, CheckState.NOT_STARTED);
    assertThat(pendingChecksList).isNotEmpty();

    checkerOperations.checker(checkerUuid).forUpdate().disable().update();
    pendingChecksList = queryPendingChecks(checkerUuid, CheckState.NOT_STARTED);
    assertThat(pendingChecksList).isEmpty();
  }

  @Test
  public void queryPendingChecksFiltersOutChecksForClosedChangesIfQueryDoesntSpecifyStatus()
      throws Exception {
    CheckerUuid checkerUuid =
        checkerOperations.newChecker().repository(project).clearQuery().create();

    checkOperations
        .newCheck(CheckKey.create(project, patchSetId, checkerUuid))
        .state(CheckState.NOT_STARTED)
        .upsert();

    PatchSet.Id patchSetId2 = createChange().getPatchSetId();
    checkOperations
        .newCheck(CheckKey.create(project, patchSetId2, checkerUuid))
        .state(CheckState.NOT_STARTED)
        .upsert();

    List<PendingChecksInfo> pendingChecksList =
        queryPendingChecks(checkerUuid, CheckState.NOT_STARTED);
    assertThat(pendingChecksList).hasSize(2);

    gApi.changes().id(patchSetId2.changeId().toString()).abandon();

    pendingChecksList = queryPendingChecks(checkerUuid, CheckState.NOT_STARTED);
    assertThat(pendingChecksList).hasSize(1);
  }

  @Test
  public void queryPendingChecksReturnsChecksForClosedChangesIfQuerySpecifiesStatus()
      throws Exception {
    CheckerUuid checkerUuid =
        checkerOperations.newChecker().repository(project).query("is:open OR is:closed").create();

    checkOperations
        .newCheck(CheckKey.create(project, patchSetId, checkerUuid))
        .state(CheckState.NOT_STARTED)
        .upsert();

    PatchSet.Id patchSetId2 = createChange().getPatchSetId();
    checkOperations
        .newCheck(CheckKey.create(project, patchSetId2, checkerUuid))
        .state(CheckState.NOT_STARTED)
        .upsert();

    List<PendingChecksInfo> pendingChecksList =
        queryPendingChecks(checkerUuid, CheckState.NOT_STARTED);
    assertThat(pendingChecksList).hasSize(2);

    gApi.changes().id(patchSetId2.changeId().toString()).abandon();

    pendingChecksList = queryPendingChecks(checkerUuid, CheckState.NOT_STARTED);
    assertThat(pendingChecksList).hasSize(2);
  }

  @Test
  public void queryPendingChecksForInvalidCheckerFails() throws Exception {
    CheckerUuid checkerUuid = checkerOperations.newChecker().repository(project).create();
    checkerOperations.checker(checkerUuid).forInvalidation().nonParseableConfig().invalidate();

    RestApiException thrown =
        assertThrows(RestApiException.class, () -> queryPendingChecks(checkerUuid));
    assertThat(thrown).hasMessageThat().contains("Cannot query pending checks");
    assertThat(thrown).hasCauseThat().isInstanceOf(ConfigInvalidException.class);
  }

  @Test
  public void queryPendingChecksForCheckerWithInvalidQueryFails() throws Exception {
    CheckerUuid checkerUuid =
        checkerOperations
            .newChecker()
            .repository(project)
            .query(CheckerTestData.INVALID_QUERY)
            .create();

    RestApiException thrown =
        assertThrows(RestApiException.class, () -> queryPendingChecks(checkerUuid));
    assertThat(thrown).hasMessageThat().contains("Cannot query pending checks");
    assertThat(thrown).hasCauseThat().isInstanceOf(ConfigInvalidException.class);
  }

  @Test
  public void queryPendingChecksWithoutAdministrateCheckersCapabilityWorks() throws Exception {
    CheckerUuid checkerUuid = checkerOperations.newChecker().repository(project).create();
    checkOperations
        .newCheck(CheckKey.create(project, patchSetId, checkerUuid))
        .state(CheckState.NOT_STARTED)
        .upsert();

    requestScopeOperations.setApiUser(user.id());
    List<PendingChecksInfo> pendingChecksList =
        queryPendingChecks(checkerUuid, CheckState.NOT_STARTED);
    assertThat(pendingChecksList).hasSize(1);
    PendingChecksInfo pendingChecks = Iterables.getOnlyElement(pendingChecksList);
    assertThat(pendingChecks).hasRepository(project);
    assertThat(pendingChecks).hasPatchSet(patchSetId);
    assertThat(pendingChecks)
        .hasPendingChecksMapThat()
        .containsExactly(checkerUuid.get(), new PendingCheckInfo(CheckState.NOT_STARTED));
  }

  @Test
  public void queryPendingChecksAnonymouslyWorks() throws Exception {
    CheckerUuid checkerUuid = checkerOperations.newChecker().repository(project).create();
    checkOperations
        .newCheck(CheckKey.create(project, patchSetId, checkerUuid))
        .state(CheckState.NOT_STARTED)
        .upsert();

    requestScopeOperations.setApiUserAnonymous();
    List<PendingChecksInfo> pendingChecksList =
        queryPendingChecks(checkerUuid, CheckState.NOT_STARTED);
    assertThat(pendingChecksList).hasSize(1);
    PendingChecksInfo pendingChecks = Iterables.getOnlyElement(pendingChecksList);
    assertThat(pendingChecks).hasRepository(project);
    assertThat(pendingChecks).hasPatchSet(patchSetId);
    assertThat(pendingChecks)
        .hasPendingChecksMapThat()
        .containsExactly(checkerUuid.get(), new PendingCheckInfo(CheckState.NOT_STARTED));
  }

  @Test
  public void pendingChecksDontIncludeChecksForNonVisibleChanges() throws Exception {
    // restrict project visibility so that it is only visible to administrators
    projectOperations
        .project(project)
        .forUpdate()
        .add(allow(Permission.READ).ref("refs/*").group(adminGroupUuid()))
        .add(block(Permission.READ).ref("refs/*").group(REGISTERED_USERS))
        .update();

    CheckerUuid checkerUuid = checkerOperations.newChecker().repository(project).create();
    checkOperations
        .newCheck(CheckKey.create(project, patchSetId, checkerUuid))
        .state(CheckState.NOT_STARTED)
        .upsert();

    // Check is returned for admin user.
    List<PendingChecksInfo> pendingChecksList =
        queryPendingChecks(checkerUuid, CheckState.NOT_STARTED);
    assertThat(pendingChecksList).isNotEmpty();

    // Check is not returned for non-admin user.
    requestScopeOperations.setApiUser(user.id());
    pendingChecksList = queryPendingChecks(checkerUuid, CheckState.NOT_STARTED);
    assertThat(pendingChecksList).isEmpty();
  }

  @Test
  public void pendingChecksDontIncludeChecksForPrivateChangesOfOtherUsers() throws Exception {
    // make change private so that it is only visible to the admin user
    gApi.changes().id(patchSetId.changeId().get()).setPrivate(true);

    CheckerUuid checkerUuid = checkerOperations.newChecker().repository(project).create();
    checkOperations
        .newCheck(CheckKey.create(project, patchSetId, checkerUuid))
        .state(CheckState.NOT_STARTED)
        .upsert();

    // Check is returned for admin user.
    List<PendingChecksInfo> pendingChecksList =
        queryPendingChecks(checkerUuid, CheckState.NOT_STARTED);
    assertThat(pendingChecksList).isNotEmpty();

    // Check is not returned for non-admin user.
    requestScopeOperations.setApiUser(user.id());
    pendingChecksList = queryPendingChecks(checkerUuid, CheckState.NOT_STARTED);
    assertThat(pendingChecksList).isEmpty();
  }

  @Test
  public void pendingChecksViaRest() throws Exception {
    CheckerUuid checkerUuid = checkerOperations.newChecker().repository(project).create();
    checkOperations
        .newCheck(CheckKey.create(project, patchSetId, checkerUuid))
        .state(CheckState.NOT_STARTED)
        .upsert();

    RestResponse r =
        adminRestSession.get(
            String.format("/plugins/checks/checks.pending/?q=checker:%s", checkerUuid.get()));
    r.assertOK();
    List<PendingChecksInfo> pendingChecksList =
        newGson().fromJson(r.getReader(), new TypeToken<List<PendingChecksInfo>>() {}.getType());
    r.consume();
    assertThat(pendingChecksList).isNotEmpty();
  }

  @Test
  public void queryPendingChecksWithScheme() throws Exception {
    // create a check with a scheme that we expect to never be returned.
    CheckerUuid checkerUuidOtherScheme =
        checkerOperations
            .newChecker()
            .uuid(CheckerUuid.parse("otherscheme:checker-1"))
            .repository(project)
            .create();
    checkOperations
        .newCheck(CheckKey.create(project, patchSetId, checkerUuidOtherScheme))
        .state(CheckState.NOT_STARTED)
        .upsert();

    CheckerUuid checkerUuid =
        checkerOperations
            .newChecker()
            .uuid(CheckerUuid.parse("test:checker-1"))
            .repository(project)
            .create();
    // Create a check with state "NOT_STARTED" that we expect to be returned.
    checkOperations
        .newCheck(CheckKey.create(project, patchSetId, checkerUuid))
        .state(CheckState.NOT_STARTED)
        .upsert();

    // Create a check with state "SCHEDULED" that we expect to be returned.
    PatchSet.Id patchSetId2 = createChange().getPatchSetId();
    checkOperations
        .newCheck(CheckKey.create(project, patchSetId2, checkerUuid))
        .state(CheckState.SCHEDULED)
        .upsert();

    // Create a check with state "SUCCESSFUL" that we expect to be ignored.
    PatchSet.Id patchSetId3 = createChange().getPatchSetId();
    checkOperations
        .newCheck(CheckKey.create(project, patchSetId3, checkerUuid))
        .state(CheckState.SUCCESSFUL)
        .upsert();

    // Create a check with state "SUCCESSFUL" that we expect to be ignored, for patchsetId.
    // by default, patchSetId2 and patchSetId3 should be NOT_STARTED, and should be returned.
    CheckerUuid checkerUuid2 =
        checkerOperations
            .newChecker()
            .uuid(CheckerUuid.parse("test:checker-2"))
            .repository(project)
            .create();
    assertThat(checkerUuid2.scheme()).isEqualTo("test");
    checkOperations
        .newCheck(CheckKey.create(project, patchSetId, checkerUuid2))
        .state(CheckState.FAILED)
        .upsert();

    List<PendingChecksInfo> pendingChecksList =
        queryPendingChecks("test", CheckState.NOT_STARTED, CheckState.SCHEDULED);
    assertThat(pendingChecksList).hasSize(4);

    // The sorting of the pendingChecksList matches the sorting in which the matching changes are
    // returned from the change index, which is by last updated timestamp. Use this knowledge here
    // to do the assertions although the REST endpoint doesn't document a guaranteed sort order.
    PendingChecksInfo pendingChecksChange = pendingChecksList.get(0);
    assertThat(pendingChecksChange).hasRepository(project);
    assertThat(pendingChecksChange).hasPatchSet(patchSetId2);
    assertThat(pendingChecksChange)
        .hasPendingChecksMapThat()
        .containsExactly(checkerUuid.get(), new PendingCheckInfo(CheckState.SCHEDULED));

    pendingChecksChange = pendingChecksList.get(1);
    assertThat(pendingChecksChange).hasRepository(project);
    assertThat(pendingChecksChange).hasPatchSet(patchSetId);
    assertThat(pendingChecksChange)
        .hasPendingChecksMapThat()
        .containsExactly(checkerUuid.get(), new PendingCheckInfo(CheckState.NOT_STARTED));

    pendingChecksChange = pendingChecksList.get(2);
    assertThat(pendingChecksChange).hasRepository(project);
    assertThat(pendingChecksChange).hasPatchSet(patchSetId3);
    assertThat(pendingChecksChange)
        .hasPendingChecksMapThat()
        .containsExactly(checkerUuid2.get(), new PendingCheckInfo(CheckState.NOT_STARTED));

    pendingChecksChange = pendingChecksList.get(3);
    assertThat(pendingChecksChange).hasRepository(project);
    assertThat(pendingChecksChange).hasPatchSet(patchSetId2);
    assertThat(pendingChecksChange)
        .hasPendingChecksMapThat()
        .containsExactly(checkerUuid2.get(), new PendingCheckInfo(CheckState.NOT_STARTED));
  }

  @Test
  public void queryOnlyExactSchemas() throws Exception {
    CheckerUuid checkerUuid =
        checkerOperations
            .newChecker()
            .uuid(CheckerUuid.parse("foobar:checker-1"))
            .repository(project)
            .create();
    // Create a check with state "NOT_STARTED" that we expect to be returned.
    checkOperations
        .newCheck(CheckKey.create(project, patchSetId, checkerUuid))
        .state(CheckState.NOT_STARTED)
        .upsert();
    assertThat(queryPendingChecks("foo", CheckState.NOT_STARTED, CheckState.SCHEDULED)).isEmpty();
    assertThat(queryPendingChecks("bar", CheckState.NOT_STARTED, CheckState.RUNNING)).isEmpty();
    assertThat(queryPendingChecks("foobar", CheckState.NOT_STARTED)).hasSize(1);
  }

  private void assertInvalidQuery(String query, String expectedMessage) {
    BadRequestException thrown =
        assertThrows(BadRequestException.class, () -> pendingChecksApi.query(query).get());
    assertThat(thrown).hasMessageThat().isEqualTo(expectedMessage);
  }

  private List<PendingChecksInfo> queryPendingChecks(String queryString) throws RestApiException {
    return pendingChecksApi.query(queryString).get();
  }

  private List<PendingChecksInfo> queryPendingChecks(
      CheckerUuid checkerUuid, CheckState... checkStates) throws RestApiException {
    return pendingChecksApi.query(buildQueryString(checkerUuid, checkStates)).get();
  }

  private List<PendingChecksInfo> queryPendingChecks(String scheme, CheckState... checkStates)
      throws RestApiException {
    return pendingChecksApi.query(buildQueryString(scheme, checkStates)).get();
  }

  private String buildQueryString(CheckerUuid checkerUuid, CheckState... checkStates) {
    StringBuilder queryString = new StringBuilder();
    queryString.append(String.format("checker:%s", checkerUuid));

    StringJoiner stateJoiner = new StringJoiner(" OR state:", " (state:", ")");
    Stream.of(checkStates).map(CheckState::name).forEach(stateJoiner::add);
    queryString.append(stateJoiner.toString());

    return queryString.toString();
  }

  private String buildQueryString(String scheme, CheckState... checkStates) {
    StringBuilder queryString = new StringBuilder();
    queryString.append(String.format("scheme:%s", scheme));

    StringJoiner stateJoiner = new StringJoiner(" OR state:", " (state:", ")");
    Stream.of(checkStates).map(CheckState::name).forEach(stateJoiner::add);
    queryString.append(stateJoiner.toString());

    return queryString.toString();
  }
}
