// Copyright (C) 2020 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package com.google.gerrit.acceptance.rest;

import static com.google.common.net.HttpHeaders.ORIGIN;
import static com.google.common.truth.Truth.assertThat;
import static com.google.gerrit.httpd.restapi.RestApiServlet.X_GERRIT_UPDATED_REF;
import static com.google.gerrit.httpd.restapi.RestApiServlet.X_GERRIT_UPDATED_REF_ENABLED;
import static org.apache.http.HttpStatus.SC_BAD_REQUEST;
import static org.apache.http.HttpStatus.SC_OK;

import com.google.common.collect.ImmutableList;
import com.google.gerrit.acceptance.AbstractDaemonTest;
import com.google.gerrit.acceptance.PushOneCommit.Result;
import com.google.gerrit.acceptance.RestResponse;
import com.google.gerrit.acceptance.config.GerritConfig;
import com.google.gerrit.acceptance.testsuite.change.ChangeOperations;
import com.google.gerrit.acceptance.testsuite.project.ProjectOperations;
import com.google.gerrit.entities.Project;
import com.google.gerrit.entities.RefNames;
import com.google.gerrit.extensions.api.changes.ChangeIdentifier;
import com.google.gerrit.extensions.api.changes.ReviewInput;
import com.google.gerrit.extensions.client.ChangeStatus;
import com.google.gerrit.extensions.restapi.Url;
import com.google.gerrit.httpd.restapi.ParameterParser;
import com.google.gerrit.httpd.restapi.RestApiServlet;
import com.google.gerrit.server.query.change.ChangeData;
import com.google.inject.Inject;
import java.io.IOException;
import java.util.regex.Pattern;
import org.apache.http.message.BasicHeader;
import org.eclipse.jgit.internal.storage.dfs.InMemoryRepository;
import org.eclipse.jgit.junit.TestRepository;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.Repository;
import org.junit.Test;

public class RestApiServletIT extends AbstractDaemonTest {
  private static String ANY_REST_API = "/accounts/self/capabilities";
  private static BasicHeader ACCEPT_STAR_HEADER = new BasicHeader("Accept", "*/*");
  private static BasicHeader X_GERRIT_UPDATED_REF_ENABLED_HEADER =
      new BasicHeader(X_GERRIT_UPDATED_REF_ENABLED, "true");
  private static Pattern ANY_SPACE = Pattern.compile("\\s");

  @Inject private ChangeOperations changeOperations;
  @Inject private ProjectOperations projectOperations;

  @Test
  public void restResponseBodyShouldBeCompactWithoutSpaces() throws Exception {
    RestResponse response = adminRestSession.getWithHeaders(ANY_REST_API, ACCEPT_STAR_HEADER);
    assertThat(response.getStatusCode()).isEqualTo(SC_OK);

    assertThat(contentWithoutMagicJson(response)).doesNotContainMatch(ANY_SPACE);
  }

  @Test
  public void restResponseBodyShouldBeCompactWithoutSpacesWhenPPIsZero() throws Exception {
    assertThat(contentWithoutMagicJson(prettyJsonRestResponse("prettyPrint", 0)))
        .doesNotContainMatch(ANY_SPACE);
  }

  @Test
  public void restResponseBodyShouldBeCompactWithoutSpacesWhenPrerryPrintIsZero() throws Exception {
    assertThat(contentWithoutMagicJson(prettyJsonRestResponse("pp", 0)))
        .doesNotContainMatch(ANY_SPACE);
  }

  @Test
  public void restResponseBodyShouldBePrettyfiedWhenPPIsOne() throws Exception {
    assertThat(contentWithoutMagicJson(prettyJsonRestResponse("pp", 1))).containsMatch(ANY_SPACE);
  }

  @Test
  public void restResponseBodyShouldBePrettyfiedWhenPrettyPrintIsOne() throws Exception {
    assertThat(contentWithoutMagicJson(prettyJsonRestResponse("prettyPrint", 1)))
        .containsMatch(ANY_SPACE);
  }

  @Test
  public void experimentRequestParamIsReserved() throws Exception {
    assertRestResponseWithParameters(SC_OK, ParameterParser.EXPERIMENT_PARAMETER, "exp1");
  }

  @Test
  public void xGerritUpdatedRefNotSetByDefault() throws Exception {
    Result change = createChange();
    String origin = adminRestSession.url();

    RestResponse response =
        adminRestSession.putWithHeaders(
            "/changes/" + change.getChangeId() + "/topic",
            /* content= */ "A",
            new BasicHeader(ORIGIN, origin));
    response.assertOK();
    assertThat(gApi.changes().id(change.getChangeId()).topic()).isEqualTo("A");

    // Meta ref updated because of topic update, but updated refs are not set by default.
    assertThat(response.getHeader(X_GERRIT_UPDATED_REF)).isNull();
  }

  @Test
  public void xGerritUpdatedRefNotSetWhenUpdatedRefNotEnabled() throws Exception {
    Result change = createChange();
    String origin = adminRestSession.url();

    RestResponse response =
        adminRestSession.putWithHeaders(
            "/changes/" + change.getChangeId() + "/topic",
            /* content= */ "A",
            new BasicHeader(ORIGIN, origin),
            new BasicHeader(X_GERRIT_UPDATED_REF_ENABLED, "false"));
    response.assertOK();
    assertThat(gApi.changes().id(change.getChangeId()).topic()).isEqualTo("A");

    // Meta ref updated because of topic update, but updated refs are not enabled.
    assertThat(response.getHeader(X_GERRIT_UPDATED_REF)).isNull();
  }

  @Test
  public void xGerritUpdatedRefNotSetForReadRequests() throws Exception {
    RestResponse response =
        adminRestSession.getWithHeaders(
            ANY_REST_API, ACCEPT_STAR_HEADER, X_GERRIT_UPDATED_REF_ENABLED_HEADER);
    assertThat(response.getStatusCode()).isEqualTo(SC_OK);
    assertThat(response.getHeader(X_GERRIT_UPDATED_REF)).isNull();
  }

  @Test
  public void xGerritUpdatedRefSetForDifferentWriteRequests() throws Exception {
    Result change = createChange();
    String origin = adminRestSession.url();
    String project = change.getChange().project().get();
    String metaRef = RefNames.changeMetaRef(change.getChange().getId());

    ObjectId originalMetaRefSha1 = getMetaRefSha1(change);

    RestResponse response =
        adminRestSession.putWithHeaders(
            "/changes/" + change.getChangeId() + "/topic",
            /* content= */ "A",
            new BasicHeader(ORIGIN, origin),
            X_GERRIT_UPDATED_REF_ENABLED_HEADER);
    response.assertOK();
    assertThat(gApi.changes().id(change.getChangeId()).topic()).isEqualTo("A");
    ObjectId firstMetaRefSha1 = getMetaRefSha1(change);

    // Meta ref updated because of topic update.
    assertThat(response.getHeader(X_GERRIT_UPDATED_REF))
        .isEqualTo(
            String.format(
                "%s~%s~%s~%s",
                Url.encode(project),
                Url.encode(metaRef),
                originalMetaRefSha1.getName(),
                firstMetaRefSha1.getName()));

    response =
        adminRestSession.putWithHeaders(
            "/changes/" + change.getChangeId() + "/topic",
            /* content= */ "B",
            new BasicHeader(ORIGIN, origin),
            X_GERRIT_UPDATED_REF_ENABLED_HEADER);
    response.assertOK();
    assertThat(gApi.changes().id(change.getChangeId()).topic()).isEqualTo("B");

    ObjectId secondMetaRefSha1 = getMetaRefSha1(change);

    // Meta ref updated again because of another topic update.
    assertThat(response.getHeader(X_GERRIT_UPDATED_REF))
        .isEqualTo(
            String.format(
                "%s~%s~%s~%s",
                Url.encode(project),
                Url.encode(metaRef),
                firstMetaRefSha1.getName(),
                secondMetaRefSha1.getName()));

    // Ensure the meta ref SHA-1 changed for the project~metaRef which means we return different
    // X-Gerrit-UpdatedRef headers.
    assertThat(secondMetaRefSha1).isNotEqualTo(firstMetaRefSha1);
  }

  @Test
  public void xGerritUpdatedRefDeleted() throws Exception {
    Result change = createChange();
    String project = change.getChange().project().get();
    String metaRef = RefNames.changeMetaRef(change.getChange().getId());
    String patchSetRef = RefNames.patchSetRef(change.getPatchSetId());

    ObjectId originalMetaRefSha1 = getMetaRefSha1(change);
    ObjectId originalchangeRefSha1 = change.getCommit().getId();

    RestResponse response =
        adminRestSession.deleteWithHeaders(
            "/changes/" + change.getChangeId(), X_GERRIT_UPDATED_REF_ENABLED_HEADER);
    response.assertNoContent();

    ImmutableList<String> headers = response.getHeaders(X_GERRIT_UPDATED_REF);

    // The change was deleted, so the refs were deleted which means they are ObjectId.zeroId().
    assertThat(headers)
        .containsExactly(
            String.format(
                "%s~%s~%s~%s",
                Url.encode(project),
                Url.encode(metaRef),
                originalMetaRefSha1.getName(),
                ObjectId.zeroId().getName()),
            String.format(
                "%s~%s~%s~%s",
                Url.encode(project),
                Url.encode(patchSetRef),
                originalchangeRefSha1.getName(),
                ObjectId.zeroId().getName()));
  }

  @Test
  public void xGerritUpdatedRefWithProjectNameContainingTilde() throws Exception {
    Project.NameKey project = createProjectOverAPI("~~pr~oje~ct~~~~", null, true, null);
    Result change = createChange(cloneProject(project, admin));
    String metaRef = RefNames.changeMetaRef(change.getChange().getId());
    String patchSetRef = RefNames.patchSetRef(change.getPatchSetId());

    ObjectId originalMetaRefSha1 = getMetaRefSha1(change);
    ObjectId originalchangeRefSha1 = change.getCommit().getId();

    RestResponse response =
        adminRestSession.deleteWithHeaders(
            "/changes/" + change.getChangeId(), X_GERRIT_UPDATED_REF_ENABLED_HEADER);
    response.assertNoContent();

    ImmutableList<String> headers = response.getHeaders(X_GERRIT_UPDATED_REF);

    // The change was deleted, so the refs were deleted which means they are ObjectId.zeroId().
    assertThat(headers)
        .containsExactly(
            String.format(
                "%s~%s~%s~%s",
                Url.encode(project.get()),
                Url.encode(metaRef),
                originalMetaRefSha1.getName(),
                ObjectId.zeroId().getName()),
            String.format(
                "%s~%s~%s~%s",
                Url.encode(project.get()),
                Url.encode(patchSetRef),
                originalchangeRefSha1.getName(),
                ObjectId.zeroId().getName()));

    // Ensures ~ gets encoded to %7E.
    assertThat(Url.encode(project.get())).endsWith("%7E%7Epr%7Eoje%7Ect%7E%7E%7E%7E");
  }

  @Test
  public void xGerritUpdatedRefSetMultipleHeadersForSubmit() throws Exception {
    Result change1 = createChange();
    Result change2 = createChange();
    String metaRef1 = RefNames.changeMetaRef(change1.getChange().getId());
    String metaRef2 = RefNames.changeMetaRef(change2.getChange().getId());

    gApi.changes().id(change1.getChangeId()).current().review(ReviewInput.approve());
    gApi.changes().id(change2.getChangeId()).current().review(ReviewInput.approve());

    Project.NameKey project = change1.getChange().project();

    try (Repository repository = repoManager.openRepository(project)) {
      ObjectId originalFirstMetaRefSha1 = getMetaRefSha1(change1);
      ObjectId originalSecondMetaRefSha1 = getMetaRefSha1(change2);
      ObjectId originalDestinationBranchSha1 =
          repository.resolve(change1.getChange().change().getDest().branch());

      RestResponse response =
          adminRestSession.postWithHeaders(
              "/changes/" + change2.getChangeId() + "/submit",
              /* content= */ null,
              X_GERRIT_UPDATED_REF_ENABLED_HEADER);
      response.assertOK();

      ObjectId firstMetaRefSha1 = getMetaRefSha1(change1);
      ObjectId secondMetaRefSha1 = getMetaRefSha1(change2);

      ImmutableList<String> headers = response.getHeaders(X_GERRIT_UPDATED_REF);

      String branch = change1.getChange().change().getDest().branch();
      String branchSha1 =
          repository
              .getRefDatabase()
              .exactRef(change1.getChange().change().getDest().branch())
              .getObjectId()
              .name();

      // During submit, all relevant meta refs of the latest patchset are updated + the destination
      // branch/es.
      assertThat(headers)
          .containsExactly(
              String.format(
                  "%s~%s~%s~%s",
                  Url.encode(project.get()),
                  Url.encode(metaRef1),
                  originalFirstMetaRefSha1.getName(),
                  firstMetaRefSha1.getName()),
              String.format(
                  "%s~%s~%s~%s",
                  Url.encode(project.get()),
                  Url.encode(metaRef2),
                  originalSecondMetaRefSha1.getName(),
                  secondMetaRefSha1.getName()),
              String.format(
                  "%s~%s~%s~%s",
                  Url.encode(project.get()),
                  Url.encode(branch),
                  originalDestinationBranchSha1.getName(),
                  branchSha1));
    }
  }

  @Test
  @GerritConfig(name = "change.submitWholeTopic", value = "true")
  public void xGerritUpdatedRefSetMultipleHeadersForSubmitTopic() throws Exception {
    String secondProject = "secondProject";
    projectOperations.newProject().name(secondProject).create();
    TestRepository<InMemoryRepository> secondRepo =
        cloneProject(Project.nameKey("secondProject"), admin);
    String topic = "topic";
    String branch = "refs/heads/master";
    Result change1 = createChange(testRepo, branch, "first change", "a.txt", "message", topic);
    Result change2 = createChange(secondRepo, branch, "second change", "b.txt", "message", topic);

    String metaRef1 = RefNames.changeMetaRef(change1.getChange().getId());
    String metaRef2 = RefNames.changeMetaRef(change2.getChange().getId());

    gApi.changes().id(change1.getChangeId()).current().review(ReviewInput.approve());
    gApi.changes().id(change2.getChangeId()).current().review(ReviewInput.approve());

    Project.NameKey project1 = change1.getChange().project();
    Project.NameKey project2 = change2.getChange().project();

    try (Repository repository1 = repoManager.openRepository(project1);
        Repository repository2 = repoManager.openRepository(project2)) {
      ObjectId originalFirstMetaRefSha1 = getMetaRefSha1(change1);
      ObjectId originalSecondMetaRefSha1 = getMetaRefSha1(change2);
      ObjectId originalDestinationBranchSha1Project1 =
          repository1.resolve(change1.getChange().change().getDest().branch());
      ObjectId originalDestinationBranchSha1Project2 =
          repository2.resolve(change2.getChange().change().getDest().branch());

      RestResponse response =
          adminRestSession.postWithHeaders(
              "/changes/" + change2.getChangeId() + "/submit",
              /* content= */ null,
              X_GERRIT_UPDATED_REF_ENABLED_HEADER);
      response.assertOK();
      assertThat(gApi.changes().id(change1.getChangeId()).get().status)
          .isEqualTo(ChangeStatus.MERGED);

      ObjectId firstMetaRefSha1 = getMetaRefSha1(change1);
      ObjectId secondMetaRefSha1 = getMetaRefSha1(change2);

      ImmutableList<String> headers = response.getHeaders(X_GERRIT_UPDATED_REF);

      String branchSha1Project1 =
          repository1
              .getRefDatabase()
              .exactRef(change1.getChange().change().getDest().branch())
              .getObjectId()
              .name();

      String branchSha1Project2 =
          repository2
              .getRefDatabase()
              .exactRef(change2.getChange().change().getDest().branch())
              .getObjectId()
              .name();

      // During submit, all relevant meta refs of the latest patchset are updated + the destination
      // branch/es.
      // TODO(paiking): This doesn't work well for torn submissions: If the changes are in
      // different projects in the same topic, and we tried to submit those changes together, it's
      // possible that the first submission only submitted one of the changes, and then the retry
      // submitted the other change. If that happens, when the user retries, they will not get the
      // meta ref updates for the change that got submitted on the previous submission attempt.
      // Ideally, submit should be idempotent and always return all meta refs on all submission
      // attempts.
      assertThat(headers)
          .containsExactly(
              String.format(
                  "%s~%s~%s~%s",
                  Url.encode(project1.get()),
                  Url.encode(metaRef1),
                  originalFirstMetaRefSha1.getName(),
                  firstMetaRefSha1.getName()),
              String.format(
                  "%s~%s~%s~%s",
                  Url.encode(project2.get()),
                  Url.encode(metaRef2),
                  originalSecondMetaRefSha1.getName(),
                  secondMetaRefSha1.getName()),
              String.format(
                  "%s~%s~%s~%s",
                  Url.encode(project1.get()),
                  Url.encode(branch),
                  originalDestinationBranchSha1Project1.getName(),
                  branchSha1Project1),
              String.format(
                  "%s~%s~%s~%s",
                  Url.encode(project2.get()),
                  Url.encode(branch),
                  originalDestinationBranchSha1Project2.getName(),
                  branchSha1Project2));
    }
  }

  @Test
  public void requestsOnRootCollectionDontRequireTrailingSlash() throws Exception {
    adminRestSession.get("/access").assertOK();
    adminRestSession.get("/accounts?q=is:active").assertOK();
    adminRestSession.get("/changes?q=status:open").assertOK();
    // GET on /config/ is not supported, hence we cannot test GET on /config
    adminRestSession.get("/groups").assertOK();
    adminRestSession.get("/projects").assertOK();
  }

  @Test
  public void testNumericChangeIdRedirectWithPrefix() throws Exception {
    int changeNumber = createChange().getChange().getId().get();

    String redirectUri = String.format("/c/%s/+/%d/", project.get(), changeNumber);
    anonymousRestSession.get("/c/" + changeNumber).assertTemporaryRedirect(redirectUri);
  }

  @Test
  public void testCommentLinkWithPrefixRedirects() throws Exception {
    int changeNumber = createChange().getChange().getId().get();
    String commentId = "ff3303fd_8341647b";

    String redirectUri =
        String.format("/c/%s/+/%d/comment/%s", project.get(), changeNumber, commentId);

    anonymousRestSession
        .get(String.format("/c/%s/comment/%s", changeNumber, commentId))
        .assertTemporaryRedirect(redirectUri);
  }

  @Test
  public void testNumericChangeIdWithExtraSegments() throws Exception {
    ChangeData changeData = createChange().getChange();
    int changeNumber = changeData.getId().get();

    assertChangeNumberWithSuffixRedirected(changeNumber, "1..2");
    assertChangeNumberWithSuffixRedirected(changeNumber, "2");
    assertChangeNumberWithSuffixRedirected(changeNumber, "2/COMMIT_MSG");
    assertChangeNumberWithSuffixRedirected(changeNumber, "2?foo=bar");
    assertChangeNumberWithSuffixRedirected(changeNumber, "2/path/to/source/file/MyClass.java");
  }

  private void assertChangeNumberWithSuffixRedirected(int changeNumber, String suffix)
      throws Exception {
    String redirectUri =
        anonymousRestSession.getUrl(
            String.format("/c/%s/+/%d/%s", project.get(), changeNumber, suffix));
    anonymousRestSession
        .get(String.format("/c/%d/%s", changeNumber, suffix))
        .assertTemporaryRedirectUri(redirectUri);
  }

  @Test
  public void testCommentLinkWithoutPrefixRedirects() throws Exception {
    int changeNumber = createChange().getChange().getId().get();
    String commentId = "ff3303fd_8341647b";

    String redirectPath =
        String.format("/c/%s/+/%d/comment/%s", project.get(), changeNumber, commentId);

    anonymousRestSession
        .get(String.format("/%s/comment/%s", changeNumber, commentId))
        .assertTemporaryRedirect(redirectPath);
  }

  @Test
  public void testNumericChangeIdRedirectWithoutPrefix() throws Exception {
    int changeNumber = createChange().getChange().getId().get();

    String redirectUri = String.format("/c/%s/+/%d/", project.get(), changeNumber);
    anonymousRestSession.get("/" + changeNumber).assertTemporaryRedirect(redirectUri);
  }

  @Test
  public void unrecognizedOptionIsRejectedAsBadRequest() throws Exception {
    String unrecognizedOption = "@";
    ChangeIdentifier changeIdentifier = changeOperations.newChange().create();
    RestResponse response =
        adminRestSession.get(
            String.format(
                "/changes/%s/submitted_together?o=%s", changeIdentifier.id(), unrecognizedOption));
    assertThat(response.getStatusCode()).isEqualTo(SC_BAD_REQUEST);

    assertThat(response.getEntityContent())
        .isEqualTo(String.format("option not recognized: %s", unrecognizedOption));
  }

  private ObjectId getMetaRefSha1(Result change) {
    return change.getChange().notes().getRevision();
  }

  private void assertRestResponseWithParameters(int status, String k, String v) throws Exception {
    RestResponse response =
        adminRestSession.getWithHeaders(ANY_REST_API + "?" + k + "=" + v, ACCEPT_STAR_HEADER);
    assertThat(response.getStatusCode()).isEqualTo(status);
  }

  private RestResponse prettyJsonRestResponse(String ppArgument, int ppValue) throws Exception {
    RestResponse response =
        adminRestSession.getWithHeaders(
            ANY_REST_API + "?" + ppArgument + "=" + ppValue, ACCEPT_STAR_HEADER);
    assertThat(response.getStatusCode()).isEqualTo(SC_OK);

    return response;
  }

  private String contentWithoutMagicJson(RestResponse response) throws IOException {
    return response.getEntityContent().substring(RestApiServlet.JSON_MAGIC.length);
  }
}
