// 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.Iterables.getOnlyElement;
import static com.google.common.truth.Truth.assertThat;
import static com.google.common.truth.Truth.assert_;
import static com.google.gerrit.extensions.client.ListChangesOption.CURRENT_REVISION;
import static javax.servlet.http.HttpServletResponse.SC_BAD_REQUEST;

import com.google.gerrit.acceptance.PushOneCommit;
import com.google.gerrit.acceptance.rest.util.RestApiCallHelper;
import com.google.gerrit.acceptance.rest.util.RestCall;
import com.google.gerrit.acceptance.rest.util.RestCall.Method;
import com.google.gerrit.acceptance.testsuite.request.RequestScopeOperations;
import com.google.gerrit.extensions.restapi.BadRequestException;
import com.google.gerrit.extensions.restapi.ResourceNotFoundException;
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.ListChecksOption;
import com.google.gerrit.plugins.checks.acceptance.AbstractCheckersTest;
import com.google.gerrit.plugins.checks.acceptance.testsuite.CheckerTestData;
import com.google.gerrit.plugins.checks.api.BlockingCondition;
import com.google.gerrit.plugins.checks.api.CheckInfo;
import com.google.gerrit.plugins.checks.api.CheckState;
import com.google.gerrit.plugins.checks.api.CheckerStatus;
import com.google.gerrit.reviewdb.client.Change;
import com.google.gerrit.reviewdb.client.PatchSet;
import com.google.gerrit.reviewdb.client.Project;
import com.google.gerrit.testing.TestTimeUtil;
import com.google.gwtorm.server.OrmException;
import com.google.inject.Inject;
import java.sql.Timestamp;
import java.time.Instant;
import java.util.concurrent.TimeUnit;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

public class GetCheckIT extends AbstractCheckersTest {
  @Inject private RequestScopeOperations requestScopeOperations;

  private String changeId;
  private PatchSet.Id patchSetId;

  @Before
  public void setUp() throws Exception {
    TestTimeUtil.resetWithClockStep(1, TimeUnit.SECONDS);
    TestTimeUtil.setClock(Timestamp.from(Instant.EPOCH));

    PushOneCommit.Result r = createChange();
    changeId = r.getChangeId();
    patchSetId = r.getPatchSetId();
  }

  @After
  public void resetTime() {
    TestTimeUtil.useSystemTime();
  }

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

    CheckKey checkKey = CheckKey.create(project, patchSetId, checkerUuid);
    checkOperations.newCheck(checkKey).setState(CheckState.RUNNING).upsert();

    assertThat(checksApiFactory.revision(patchSetId).id(checkerUuid).get())
        .isEqualTo(checkOperations.check(checkKey).asInfo());
  }

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

    CheckKey checkKey = CheckKey.create(project, patchSetId, checkerUuid);
    checkOperations.newCheck(checkKey).upsert();

    assertThat(getCheckInfo(patchSetId, checkerUuid).repository).isEqualTo(project.get());
    assertThat(getCheckInfo(patchSetId, checkerUuid, ListChecksOption.CHECKER).repository)
        .isEqualTo(project.get());
  }

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

    CheckKey checkKey = CheckKey.create(project, patchSetId, checkerUuid);
    checkOperations.newCheck(checkKey).upsert();

    assertThat(getCheckInfo(patchSetId, checkerUuid).changeNumber)
        .isEqualTo(patchSetId.getParentKey().get());
    assertThat(getCheckInfo(patchSetId, checkerUuid, ListChecksOption.CHECKER).changeNumber)
        .isEqualTo(patchSetId.getParentKey().get());
  }

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

    CheckKey checkKey = CheckKey.create(project, patchSetId, checkerUuid);
    checkOperations.newCheck(checkKey).upsert();

    assertThat(getCheckInfo(patchSetId, checkerUuid).patchSetId).isEqualTo(patchSetId.get());
    assertThat(getCheckInfo(patchSetId, checkerUuid, ListChecksOption.CHECKER).patchSetId)
        .isEqualTo(patchSetId.get());
  }

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

    CheckKey checkKey = CheckKey.create(project, patchSetId, checkerUuid);
    checkOperations.newCheck(checkKey).upsert();

    assertThat(getCheckInfo(patchSetId, checkerUuid).checkerUuid).isEqualTo(checkerUuid.get());
    assertThat(getCheckInfo(patchSetId, checkerUuid, ListChecksOption.CHECKER).checkerUuid)
        .isEqualTo(checkerUuid.get());
  }

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

    CheckKey checkKey = CheckKey.create(project, patchSetId, checkerUuid);
    checkOperations.newCheck(checkKey).setState(CheckState.RUNNING).upsert();

    assertThat(getCheckInfo(patchSetId, checkerUuid).state).isEqualTo(CheckState.RUNNING);
    assertThat(getCheckInfo(patchSetId, checkerUuid, ListChecksOption.CHECKER).state)
        .isEqualTo(CheckState.RUNNING);
  }

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

    CheckKey checkKey = CheckKey.create(project, patchSetId, checkerUuid);
    checkOperations.newCheck(checkKey).upsert();

    assertThat(getCheckInfo(patchSetId, checkerUuid).state).isEqualTo(CheckState.NOT_STARTED);
    assertThat(getCheckInfo(patchSetId, checkerUuid, ListChecksOption.CHECKER).state)
        .isEqualTo(CheckState.NOT_STARTED);
  }

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

    Timestamp expectedCreationTimestamp = TestTimeUtil.getCurrentTimestamp();
    CheckKey checkKey = CheckKey.create(project, patchSetId, checkerUuid);
    checkOperations.newCheck(checkKey).upsert();

    assertThat(getCheckInfo(patchSetId, checkerUuid).created).isEqualTo(expectedCreationTimestamp);
    assertThat(getCheckInfo(patchSetId, checkerUuid, ListChecksOption.CHECKER).created)
        .isEqualTo(expectedCreationTimestamp);
  }

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

    Timestamp expectedUpdatedTimestamp = TestTimeUtil.getCurrentTimestamp();
    CheckKey checkKey = CheckKey.create(project, patchSetId, checkerUuid);
    checkOperations.newCheck(checkKey).upsert();

    assertThat(getCheckInfo(patchSetId, checkerUuid).created).isEqualTo(expectedUpdatedTimestamp);
    assertThat(getCheckInfo(patchSetId, checkerUuid, ListChecksOption.CHECKER).created)
        .isEqualTo(expectedUpdatedTimestamp);
  }

  @Test
  public void getCheckReturnsCheckerNameOnlyForCheckerOption() throws Exception {
    CheckerUuid checkerUuid =
        checkerOperations.newChecker().repository(project).name("My Checker").create();

    CheckKey checkKey = CheckKey.create(project, patchSetId, checkerUuid);
    checkOperations.newCheck(checkKey).upsert();

    assertThat(getCheckInfo(patchSetId, checkerUuid).checkerName).isNull();
    assertThat(getCheckInfo(patchSetId, checkerUuid, ListChecksOption.CHECKER).checkerName)
        .isEqualTo("My Checker");
  }

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

    CheckKey checkKey = CheckKey.create(project, patchSetId, checkerUuid);
    checkOperations.newCheck(checkKey).upsert();

    assertThat(getCheckInfo(patchSetId, checkerUuid).checkerStatus).isNull();
    assertThat(getCheckInfo(patchSetId, checkerUuid, ListChecksOption.CHECKER).checkerStatus)
        .isEqualTo(CheckerStatus.ENABLED);
  }

  @Test
  public void getCheckReturnsBlockingConditionsOnlyForCheckerOption() throws Exception {
    CheckerUuid checkerUuid =
        checkerOperations
            .newChecker()
            .repository(project)
            .blockingConditions(BlockingCondition.STATE_NOT_PASSING)
            .create();

    CheckKey checkKey = CheckKey.create(project, patchSetId, checkerUuid);
    checkOperations.newCheck(checkKey).upsert();

    assertThat(getCheckInfo(patchSetId, checkerUuid).blocking).isNull();
    assertThat(getCheckInfo(patchSetId, checkerUuid, ListChecksOption.CHECKER).blocking)
        .containsExactly(BlockingCondition.STATE_NOT_PASSING);
  }

  @Test
  public void getCheckWithCheckerOptionReturnsCheckEvenIfCheckerIsInvalid() throws Exception {
    CheckerUuid checkerUuid =
        checkerOperations.newChecker().repository(project).name("My Checker").create();

    CheckKey checkKey = CheckKey.create(project, patchSetId, checkerUuid);
    checkOperations.newCheck(checkKey).setState(CheckState.RUNNING).upsert();

    checkerOperations.checker(checkerUuid).forUpdate().forceInvalidConfig().update();

    CheckInfo check = getCheckInfo(patchSetId, checkerUuid, ListChecksOption.CHECKER);
    assertThat(check).isNotNull();

    // Checker fields are not set.
    assertThat(check.checkerName).isNull();
    assertThat(check.blocking).isNull();
    assertThat(check.checkerStatus).isNull();

    // Check that at least some non-checker fields are set to ensure that we didn't get a completely
    // empty CheckInfo.
    assertThat(check.repository).isEqualTo(project.get());
    assertThat(check.checkerUuid).isEqualTo(checkerUuid.get());
    assertThat(check.changeNumber).isEqualTo(patchSetId.getParentKey().get());
    assertThat(check.patchSetId).isEqualTo(patchSetId.get());
    assertThat(check.state).isEqualTo(CheckState.RUNNING);
  }

  @Test
  public void getCheckForCheckerThatDoesNotApplyToTheProject() throws Exception {
    Project.NameKey otherProject = createProjectOverAPI("other", null, true, null);
    CheckerUuid checkerUuid = checkerOperations.newChecker().repository(otherProject).create();
    checkOperations.newCheck(CheckKey.create(project, patchSetId, checkerUuid)).upsert();

    assertThat(getCheckInfo(patchSetId, checkerUuid)).isNotNull();
  }

  @Test
  public void getCheckForCheckerThatDoesNotApplyToTheChange() throws Exception {
    CheckerUuid checkerUuid =
        checkerOperations.newChecker().repository(project).query("message:not-matching").create();
    checkOperations.newCheck(CheckKey.create(project, patchSetId, checkerUuid)).upsert();

    assertThat(getCheckInfo(patchSetId, checkerUuid)).isNotNull();
  }

  @Test
  public void getCheckForCheckerWithUnsupportedOperatorInQuery() throws Exception {
    CheckerUuid checkerUuid =
        checkerOperations
            .newChecker()
            .repository(project)
            .query(CheckerTestData.QUERY_WITH_UNSUPPORTED_OPERATOR)
            .create();
    checkOperations.newCheck(CheckKey.create(project, patchSetId, checkerUuid)).upsert();

    assertThat(getCheckInfo(patchSetId, checkerUuid)).isNotNull();
  }

  @Test
  public void getCheckForCheckerWithInvalidQuery() throws Exception {
    CheckerUuid checkerUuid =
        checkerOperations
            .newChecker()
            .repository(project)
            .query(CheckerTestData.INVALID_QUERY)
            .create();
    checkOperations.newCheck(CheckKey.create(project, patchSetId, checkerUuid)).upsert();

    assertThat(getCheckInfo(patchSetId, checkerUuid)).isNotNull();
  }

  @Test
  public void getCheckForDisabledChecker() throws Exception {
    CheckerUuid checkerUuid = checkerOperations.newChecker().repository(project).create();
    checkOperations.newCheck(CheckKey.create(project, patchSetId, checkerUuid)).upsert();
    checkerOperations.checker(checkerUuid).forUpdate().disable().update();

    assertThat(getCheckInfo(patchSetId, checkerUuid)).isNotNull();
  }

  @Test
  public void getCheckForInvalidChecker() throws Exception {
    CheckerUuid checkerUuid = checkerOperations.newChecker().repository(project).create();
    checkOperations.newCheck(CheckKey.create(project, patchSetId, checkerUuid)).upsert();
    checkerOperations.checker(checkerUuid).forUpdate().forceInvalidConfig().update();

    assertThat(getCheckInfo(patchSetId, checkerUuid)).isNotNull();
  }

  @Test
  public void noBackfillForInvalidChecker() throws Exception {
    CheckerUuid checkerUuid = checkerOperations.newChecker().repository(project).create();
    assertThat(getCheckInfo(patchSetId, checkerUuid)).isNotNull();

    checkerOperations.checker(checkerUuid).forUpdate().forceInvalidConfig().update();
    assertCheckNotFound(patchSetId, checkerUuid);
  }

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

    CheckKey checkKey1 = CheckKey.create(project, patchSetId, checkerUuid);
    checkOperations.newCheck(checkKey1).setState(CheckState.FAILED).upsert();

    PatchSet.Id currentPatchSetId = createPatchSet();
    CheckKey checkKey2 = CheckKey.create(project, currentPatchSetId, checkerUuid);
    checkOperations.newCheck(checkKey2).setState(CheckState.RUNNING).upsert();

    // get check for the old patch set
    assertThat(checksApiFactory.revision(patchSetId).id(checkerUuid).get())
        .isEqualTo(checkOperations.check(checkKey1).asInfo());

    // get check for the current patch set (2 ways)
    assertThat(checksApiFactory.revision(currentPatchSetId).id(checkerUuid).get())
        .isEqualTo(checkOperations.check(checkKey2).asInfo());
    assertThat(
            checksApiFactory
                .currentRevision(currentPatchSetId.getParentKey())
                .id(checkerUuid)
                .get())
        .isEqualTo(checkOperations.check(checkKey2).asInfo());
  }

  @Test
  public void noBackfillForNonCurrentPatchSet() throws Exception {
    CheckerUuid checkerUuid = checkerOperations.newChecker().repository(project).create();
    PatchSet.Id currentPatchSetId = createPatchSet();
    assertCheckNotFound(patchSetId, checkerUuid);
    assertThat(getCheckInfo(currentPatchSetId, checkerUuid)).isNotNull();
  }

  @Test
  public void getCheckForNonExistingChecker() throws Exception {
    CheckerUuid checkerUuid = checkerOperations.newChecker().repository(project).create();
    checkOperations.newCheck(CheckKey.create(project, patchSetId, checkerUuid)).upsert();
    checkerOperations.checker(checkerUuid).forUpdate().deleteRef().update();

    assertThat(getCheckInfo(patchSetId, checkerUuid)).isNotNull();
  }

  @Test
  public void getNonExistingCheckBackfillsForRelevantChecker() throws Exception {
    String topic = name("topic");
    Change.Id changeId = patchSetId.getParentKey();
    CheckerUuid checkerUuid =
        checkerOperations.newChecker().repository(project).query("topic:" + topic).create();
    CheckKey checkKey = CheckKey.create(project, patchSetId, checkerUuid);

    assertCheckNotFound(patchSetId, checkerUuid);

    gApi.changes().id(changeId.get()).topic(topic);

    Timestamp psCreated = getPatchSetCreated(changeId);
    CheckInfo expected = new CheckInfo();
    expected.repository = checkKey.repository().get();
    expected.changeNumber = checkKey.patchSet().getParentKey().get();
    expected.patchSetId = checkKey.patchSet().get();
    expected.checkerUuid = checkKey.checkerUuid().get();
    expected.state = CheckState.NOT_STARTED;
    expected.created = psCreated;
    expected.updated = psCreated;
    assertThat(getCheckInfo(patchSetId, checkerUuid)).isEqualTo(expected);
  }

  @Test
  public void getNonExistingCheckDoesNotBackfillForDisabledChecker() throws Exception {
    Change.Id changeId = patchSetId.getParentKey();
    CheckerUuid checkerUuid = checkerOperations.newChecker().repository(project).create();
    CheckKey checkKey = CheckKey.create(project, patchSetId, checkerUuid);

    Timestamp psCreated = getPatchSetCreated(changeId);
    CheckInfo expected = new CheckInfo();
    expected.repository = checkKey.repository().get();
    expected.changeNumber = checkKey.patchSet().getParentKey().get();
    expected.patchSetId = checkKey.patchSet().get();
    expected.checkerUuid = checkKey.checkerUuid().get();
    expected.state = CheckState.NOT_STARTED;
    expected.created = psCreated;
    expected.updated = psCreated;
    assertThat(getCheckInfo(patchSetId, checkerUuid)).isEqualTo(expected);

    checkerOperations.checker(checkerUuid).forUpdate().disable().update();

    assertCheckNotFound(patchSetId, checkerUuid);
  }

  @Test
  public void getCheckForInvalidCheckerUuid() throws Exception {
    exception.expect(BadRequestException.class);
    exception.expectMessage("invalid checker UUID: " + CheckerTestData.INVALID_UUID);
    checksApiFactory.revision(patchSetId).id(CheckerTestData.INVALID_UUID);
  }

  @Test
  public void getCheckForInvalidCheckerUuidViaRest() throws Exception {
    RestApiCallHelper.execute(
        adminRestSession,
        RestCall.builder(Method.GET, "/changes/%s/revisions/%s/checks~checks/%s")
            .expectedResponseCode(SC_BAD_REQUEST)
            .expectedMessage("invalid checker UUID: " + CheckerTestData.INVALID_UUID)
            .build(),
        Integer.toString(patchSetId.getParentKey().get()),
        Integer.toString(patchSetId.get()),
        CheckerTestData.INVALID_UUID);
  }

  @Test
  public void getCheckWithoutAdministrateCheckers() throws Exception {
    requestScopeOperations.setApiUser(user.getId());

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

    assertThat(getCheckInfo(patchSetId, checkerUuid)).isNotNull();
  }

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

    gApi.changes().id(patchSetId.getParentKey().get()).delete();

    try {
      getCheckInfo(patchSetId, checkerUuid);
      assert_().fail("expected ResourceNotFoundException");
    } catch (ResourceNotFoundException e) {
      assertThat(e)
          .hasMessageThat()
          .ignoringCase()
          .contains(String.format("change %d", patchSetId.getParentKey().get()));
    }
  }

  private CheckInfo getCheckInfo(
      PatchSet.Id patchSetId, CheckerUuid checkerUuid, ListChecksOption... options)
      throws RestApiException, OrmException {
    return checksApiFactory.revision(patchSetId).id(checkerUuid).get(options);
  }

  private Timestamp getPatchSetCreated(Change.Id changeId) throws RestApiException {
    return getOnlyElement(
            gApi.changes().id(changeId.get()).get(CURRENT_REVISION).revisions.values())
        .created;
  }

  private void assertCheckNotFound(PatchSet.Id patchSetId, CheckerUuid checkerUuid)
      throws Exception {
    try {
      getCheckInfo(patchSetId, checkerUuid);
      assert_().fail("expected ResourceNotFoundException");
    } catch (ResourceNotFoundException e) {
      assertThat(e)
          .hasMessageThat()
          .isEqualTo(
              String.format(
                  "Patch set %s in repository %s doesn't have check for checker %s.",
                  patchSetId, project, checkerUuid));
    }
  }

  private PatchSet.Id createPatchSet() throws Exception {
    PushOneCommit.Result r = amendChange(changeId);
    PatchSet.Id currentPatchSetId = r.getPatchSetId();
    assertThat(patchSetId.changeId).isEqualTo(currentPatchSetId.changeId);
    assertThat(patchSetId.get()).isLessThan(currentPatchSetId.get());
    return currentPatchSetId;
  }
}
