// Copyright (C) 2014 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.edit;

import static com.google.common.collect.Iterables.getOnlyElement;
import static com.google.common.truth.Truth.assertThat;
import static com.google.gerrit.server.group.SystemGroupBackend.REGISTERED_USERS;
import static java.nio.charset.StandardCharsets.UTF_8;
import static java.util.concurrent.TimeUnit.SECONDS;

import com.google.common.base.Optional;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Lists;
import com.google.gerrit.acceptance.AbstractDaemonTest;
import com.google.gerrit.acceptance.PushOneCommit;
import com.google.gerrit.acceptance.RestResponse;
import com.google.gerrit.acceptance.TestProjectInput;
import com.google.gerrit.common.RawInputUtil;
import com.google.gerrit.common.data.LabelType;
import com.google.gerrit.common.data.Permission;
import com.google.gerrit.extensions.api.changes.ReviewInput;
import com.google.gerrit.extensions.client.InheritableBoolean;
import com.google.gerrit.extensions.client.ListChangesOption;
import com.google.gerrit.extensions.common.ApprovalInfo;
import com.google.gerrit.extensions.common.ChangeInfo;
import com.google.gerrit.extensions.common.ChangeMessageInfo;
import com.google.gerrit.extensions.common.DiffInfo;
import com.google.gerrit.extensions.common.EditInfo;
import com.google.gerrit.extensions.common.FileInfo;
import com.google.gerrit.extensions.restapi.BinaryResult;
import com.google.gerrit.extensions.restapi.ResourceNotFoundException;
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.reviewdb.server.ReviewDb;
import com.google.gerrit.server.change.ChangeEdits.EditMessage;
import com.google.gerrit.server.change.ChangeEdits.Post;
import com.google.gerrit.server.change.ChangeEdits.Put;
import com.google.gerrit.server.change.FileContentUtil;
import com.google.gerrit.server.edit.ChangeEdit;
import com.google.gerrit.server.edit.ChangeEditModifier;
import com.google.gerrit.server.edit.ChangeEditUtil;
import com.google.gerrit.server.edit.UnchangedCommitMessageException;
import com.google.gerrit.server.git.ProjectConfig;
import com.google.gerrit.server.project.InvalidChangeOperationException;
import com.google.gerrit.server.project.Util;
import com.google.gerrit.testutil.TestTimeUtil;
import com.google.gson.reflect.TypeToken;
import com.google.gson.stream.JsonReader;
import com.google.gwtorm.server.SchemaFactory;
import com.google.inject.Inject;

import org.apache.commons.codec.binary.StringUtils;
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.PersonIdent;
import org.eclipse.jgit.lib.RefUpdate;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.revwalk.RevWalk;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;

import java.io.ByteArrayOutputStream;
import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

public class ChangeEditIT extends AbstractDaemonTest {

  private static final String FILE_NAME = "foo";
  private static final String FILE_NAME2 = "foo2";
  private static final String FILE_NAME3 = "foo3";
  private static final byte[] CONTENT_OLD = "bar".getBytes(UTF_8);
  private static final byte[] CONTENT_NEW = "baz".getBytes(UTF_8);
  private static final String CONTENT_NEW2_STR = "quxÄÜÖßµ";
  private static final byte[] CONTENT_NEW2 = CONTENT_NEW2_STR.getBytes(UTF_8);

  @Inject
  private SchemaFactory<ReviewDb> reviewDbProvider;

  @Inject
  private ChangeEditUtil editUtil;

  @Inject
  private ChangeEditModifier modifier;

  @Inject
  private FileContentUtil fileUtil;

  private Change change;
  private String changeId;
  private Change change2;
  private String changeId2;
  private PatchSet ps;
  private PatchSet ps2;

  @BeforeClass
  public static void setTimeForTesting() {
    TestTimeUtil.resetWithClockStep(1, SECONDS);
  }

  @AfterClass
  public static void restoreTime() {
    TestTimeUtil.useSystemTime();
  }

  @Before
  public void setUp() throws Exception {
    db = reviewDbProvider.open();
    changeId = newChange(admin.getIdent());
    ps = getCurrentPatchSet(changeId);
    amendChange(admin.getIdent(), changeId);
    change = getChange(changeId);
    assertThat(ps).isNotNull();
    changeId2 = newChange2(admin.getIdent());
    change2 = getChange(changeId2);
    assertThat(change2).isNotNull();
    ps2 = getCurrentPatchSet(changeId2);
    assertThat(ps2).isNotNull();
  }

  @After
  public void cleanup() {
    db.close();
  }

  @Test
  public void parseEditRevision() throws Exception {
    assertThat(modifier.createEdit(change, ps)).isEqualTo(RefUpdate.Result.NEW);

    // check that '0' is parsed as edit revision
    gApi.changes().id(change.getChangeId()).revision(0).comments();

    // check that 'edit' is parsed as edit revision
    gApi.changes().id(change.getChangeId()).revision("edit").comments();
  }

  @Test
  public void deleteEdit() throws Exception {
    assertThat(modifier.createEdit(change, ps)).isEqualTo(RefUpdate.Result.NEW);
    assertThat(
        modifier.modifyFile(editUtil.byChange(change).get(), FILE_NAME,
            RawInputUtil.create(CONTENT_NEW))).isEqualTo(RefUpdate.Result.FORCED);
    editUtil.delete(editUtil.byChange(change).get());
    assertThat(editUtil.byChange(change).isPresent()).isFalse();
  }

  @Test
  public void publishEdit() throws Exception {
    assertThat(modifier.createEdit(change, getCurrentPatchSet(changeId)))
        .isEqualTo(RefUpdate.Result.NEW);
    assertThat(
        modifier.modifyFile(editUtil.byChange(change).get(), FILE_NAME,
            RawInputUtil.create(CONTENT_NEW2))).isEqualTo(RefUpdate.Result.FORCED);
    editUtil.publish(editUtil.byChange(change).get());
    Optional<ChangeEdit> edit = editUtil.byChange(change);
    assertThat(edit.isPresent()).isFalse();
    assertChangeMessages(change,
        ImmutableList.of("Uploaded patch set 1.",
            "Uploaded patch set 2.",
            "Patch Set 3: Published edit on patch set 2."));
  }

  @Test
  public void publishEditRest() throws Exception {
    PatchSet oldCurrentPatchSet = getCurrentPatchSet(changeId);
    assertThat(modifier.createEdit(change, oldCurrentPatchSet)).isEqualTo(
        RefUpdate.Result.NEW);
    assertThat(
        modifier.modifyFile(editUtil.byChange(change).get(), FILE_NAME,
            RawInputUtil.create(CONTENT_NEW))).isEqualTo(RefUpdate.Result.FORCED);
    Optional<ChangeEdit> edit = editUtil.byChange(change);
    adminRestSession.post(urlPublish()).assertNoContent();
    edit = editUtil.byChange(change);
    assertThat(edit.isPresent()).isFalse();
    PatchSet newCurrentPatchSet = getCurrentPatchSet(changeId);
    assertThat(newCurrentPatchSet.getId()).isNotEqualTo(oldCurrentPatchSet.getId());
    assertChangeMessages(change,
        ImmutableList.of("Uploaded patch set 1.",
            "Uploaded patch set 2.",
            "Patch Set 3: Published edit on patch set 2."));
  }

  @Test
  public void deleteEditRest() throws Exception {
    assertThat(modifier.createEdit(change, ps)).isEqualTo(RefUpdate.Result.NEW);
    assertThat(
        modifier.modifyFile(editUtil.byChange(change).get(), FILE_NAME,
            RawInputUtil.create(CONTENT_NEW))).isEqualTo(RefUpdate.Result.FORCED);
    Optional<ChangeEdit> edit = editUtil.byChange(change);
    adminRestSession.delete(urlEdit()).assertNoContent();
    edit = editUtil.byChange(change);
    assertThat(edit.isPresent()).isFalse();
  }

  @Test
  public void publishEditRestWithoutCLA() throws Exception {
    setUseContributorAgreements(InheritableBoolean.TRUE);
    PatchSet oldCurrentPatchSet = getCurrentPatchSet(changeId);
    assertThat(modifier.createEdit(change, oldCurrentPatchSet)).isEqualTo(
        RefUpdate.Result.NEW);
    assertThat(
        modifier.modifyFile(editUtil.byChange(change).get(), FILE_NAME,
            RawInputUtil.create(CONTENT_NEW))).isEqualTo(RefUpdate.Result.FORCED);
    adminRestSession.post(urlPublish()).assertForbidden();
    setUseContributorAgreements(InheritableBoolean.FALSE);
    adminRestSession.post(urlPublish()).assertNoContent();
  }

  @Test
  public void rebaseEdit() throws Exception {
    assertThat(modifier.createEdit(change, ps)).isEqualTo(RefUpdate.Result.NEW);
    assertThat(
        modifier.modifyFile(editUtil.byChange(change).get(), FILE_NAME,
            RawInputUtil.create(CONTENT_NEW))).isEqualTo(RefUpdate.Result.FORCED);
    ChangeEdit edit = editUtil.byChange(change).get();
    PatchSet current = getCurrentPatchSet(changeId);
    assertThat(edit.getBasePatchSet().getPatchSetId()).isEqualTo(
        current.getPatchSetId() - 1);
    Date beforeRebase = edit.getEditCommit().getCommitterIdent().getWhen();
    modifier.rebaseEdit(edit, current);
    edit = editUtil.byChange(change).get();
    assertByteArray(fileUtil.getContent(projectCache.get(edit.getChange().getProject()),
        ObjectId.fromString(edit.getRevision().get()), FILE_NAME), CONTENT_NEW);
    assertByteArray(fileUtil.getContent(projectCache.get(edit.getChange().getProject()),
        ObjectId.fromString(edit.getRevision().get()), FILE_NAME2), CONTENT_NEW2);
    assertThat(edit.getBasePatchSet().getPatchSetId()).isEqualTo(
        current.getPatchSetId());
    Date afterRebase = edit.getEditCommit().getCommitterIdent().getWhen();
    assertThat(beforeRebase.equals(afterRebase)).isFalse();
  }

  @Test
  public void rebaseEditRest() throws Exception {
    assertThat(modifier.createEdit(change, ps)).isEqualTo(RefUpdate.Result.NEW);
    assertThat(
        modifier.modifyFile(editUtil.byChange(change).get(), FILE_NAME,
            RawInputUtil.create(CONTENT_NEW))).isEqualTo(RefUpdate.Result.FORCED);
    ChangeEdit edit = editUtil.byChange(change).get();
    PatchSet current = getCurrentPatchSet(changeId);
    assertThat(edit.getBasePatchSet().getPatchSetId()).isEqualTo(
        current.getPatchSetId() - 1);
    Date beforeRebase = edit.getEditCommit().getCommitterIdent().getWhen();
    adminRestSession.post(urlRebase()).assertNoContent();
    edit = editUtil.byChange(change).get();
    assertByteArray(fileUtil.getContent(projectCache.get(edit.getChange().getProject()),
        ObjectId.fromString(edit.getRevision().get()), FILE_NAME), CONTENT_NEW);
    assertByteArray(fileUtil.getContent(projectCache.get(edit.getChange().getProject()),
        ObjectId.fromString(edit.getRevision().get()), FILE_NAME2), CONTENT_NEW2);
    assertThat(edit.getBasePatchSet().getPatchSetId()).isEqualTo(
        current.getPatchSetId());
    Date afterRebase = edit.getEditCommit().getCommitterIdent().getWhen();
    assertThat(afterRebase).isNotEqualTo(beforeRebase);
  }

  @Test
  public void rebaseEditWithConflictsRest_Conflict() throws Exception {
    PatchSet current = getCurrentPatchSet(changeId2);
    assertThat(modifier.createEdit(change2, current)).isEqualTo(RefUpdate.Result.NEW);
    assertThat(
        modifier.modifyFile(editUtil.byChange(change2).get(), FILE_NAME,
            RawInputUtil.create(CONTENT_NEW))).isEqualTo(RefUpdate.Result.FORCED);
    ChangeEdit edit = editUtil.byChange(change2).get();
    assertThat(edit.getBasePatchSet().getPatchSetId()).isEqualTo(
        current.getPatchSetId());
    PushOneCommit push =
        pushFactory.create(db, admin.getIdent(), testRepo, PushOneCommit.SUBJECT, FILE_NAME,
            new String(CONTENT_NEW2), changeId2);
    push.to("refs/for/master").assertOkStatus();
    adminRestSession.post(urlRebase()).assertConflict();
  }

  @Test
  public void updateExistingFile() throws Exception {
    assertThat(modifier.createEdit(change, ps)).isEqualTo(RefUpdate.Result.NEW);
    Optional<ChangeEdit> edit = editUtil.byChange(change);
    assertThat(modifier.modifyFile(edit.get(), FILE_NAME, RawInputUtil.create(CONTENT_NEW)))
        .isEqualTo(RefUpdate.Result.FORCED);
    edit = editUtil.byChange(change);
    assertByteArray(fileUtil.getContent(projectCache.get(edit.get().getChange().getProject()),
        ObjectId.fromString(edit.get().getRevision().get()), FILE_NAME), CONTENT_NEW);
    editUtil.delete(edit.get());
    edit = editUtil.byChange(change);
    assertThat(edit.isPresent()).isFalse();
  }

  @Test
  @TestProjectInput(createEmptyCommit = false)
  public void updateRootCommitMessage() throws Exception {
    // Re-clone empty repo; TestRepository doesn't let us reset to unborn head.
    testRepo = cloneProject(project);
    changeId = newChange(admin.getIdent());
    change = getChange(changeId);

    assertThat(modifier.createEdit(change, getCurrentPatchSet(changeId)))
        .isEqualTo(RefUpdate.Result.NEW);
    Optional<ChangeEdit> edit = editUtil.byChange(change);
    assertThat(edit.get().getEditCommit().getParentCount()).isEqualTo(0);

    String msg = String.format("New commit message\n\nChange-Id: %s\n",
        change.getKey());
    assertThat(modifier.modifyMessage(edit.get(), msg))
        .isEqualTo(RefUpdate.Result.FORCED);
    edit = editUtil.byChange(change);
    assertThat(edit.get().getEditCommit().getFullMessage()).isEqualTo(msg);
  }

  @Test
  public void updateMessageNoChange() throws Exception {
    assertThat(modifier.createEdit(change, getCurrentPatchSet(changeId)))
        .isEqualTo(RefUpdate.Result.NEW);
    Optional<ChangeEdit> edit = editUtil.byChange(change);

    exception.expect(UnchangedCommitMessageException.class);
    exception.expectMessage(
        "New commit message cannot be same as existing commit message");
    modifier.modifyMessage(
        edit.get(),
        edit.get().getEditCommit().getFullMessage());
  }

  @Test
  public void updateMessageOnlyAddTrailingNewLines() throws Exception {
    assertThat(modifier.createEdit(change, getCurrentPatchSet(changeId)))
        .isEqualTo(RefUpdate.Result.NEW);
    Optional<ChangeEdit> edit = editUtil.byChange(change);

    exception.expect(UnchangedCommitMessageException.class);
    exception.expectMessage(
        "New commit message cannot be same as existing commit message");
    modifier.modifyMessage(
        edit.get(),
        edit.get().getEditCommit().getFullMessage() + "\n\n");
  }

  @Test
  public void updateMessage() throws Exception {
    assertThat(modifier.createEdit(change, getCurrentPatchSet(changeId)))
        .isEqualTo(RefUpdate.Result.NEW);
    Optional<ChangeEdit> edit = editUtil.byChange(change);
    String msg = String.format("New commit message\n\nChange-Id: %s\n",
        change.getKey());
    assertThat(modifier.modifyMessage(edit.get(), msg)).isEqualTo(
        RefUpdate.Result.FORCED);
    edit = editUtil.byChange(change);
    assertThat(edit.get().getEditCommit().getFullMessage()).isEqualTo(msg);

    editUtil.publish(edit.get());
    assertThat(editUtil.byChange(change).isPresent()).isFalse();

    ChangeInfo info = get(changeId, ListChangesOption.CURRENT_COMMIT,
        ListChangesOption.CURRENT_REVISION);
    assertThat(info.revisions.get(info.currentRevision).commit.message)
        .isEqualTo(msg);

    assertChangeMessages(change,
        ImmutableList.of("Uploaded patch set 1.",
            "Uploaded patch set 2.",
            "Patch Set 3: Commit message was updated."));
  }

  @Test
  public void updateMessageRest() throws Exception {
    adminRestSession.get(urlEditMessage(false)).assertNotFound();
    EditMessage.Input in = new EditMessage.Input();
    in.message = String.format("New commit message\n\n" +
        CONTENT_NEW2_STR + "\n\nChange-Id: %s\n",
        change.getKey());
    adminRestSession.put(urlEditMessage(false), in).assertNoContent();
    RestResponse r = adminRestSession.getJsonAccept(urlEditMessage(false));
    r.assertOK();
    assertThat(readContentFromJson(r)).isEqualTo(in.message);
    Optional<ChangeEdit> edit = editUtil.byChange(change);
    assertThat(edit.get().getEditCommit().getFullMessage())
        .isEqualTo(in.message);
    in.message = String.format("New commit message2\n\nChange-Id: %s\n",
        change.getKey());
    adminRestSession.put(urlEditMessage(false), in).assertNoContent();
    edit = editUtil.byChange(change);
    assertThat(edit.get().getEditCommit().getFullMessage())
        .isEqualTo(in.message);

    r = adminRestSession.getJsonAccept(urlEditMessage(true));
    try (Repository repo = repoManager.openRepository(project);
        RevWalk rw = new RevWalk(repo)) {
      RevCommit commit = rw.parseCommit(
          ObjectId.fromString(ps.getRevision().get()));
      assertThat(readContentFromJson(r)).isEqualTo(commit.getFullMessage());
    }

    editUtil.publish(edit.get());
    assertChangeMessages(change,
        ImmutableList.of("Uploaded patch set 1.",
            "Uploaded patch set 2.",
            "Patch Set 3: Commit message was updated."));
  }

  @Test
  public void retrieveEdit() throws Exception {
    adminRestSession.get(urlEdit()).assertNoContent();
    assertThat(modifier.createEdit(change, ps)).isEqualTo(RefUpdate.Result.NEW);
    Optional<ChangeEdit> edit = editUtil.byChange(change);
    assertThat(modifier.modifyFile(edit.get(), FILE_NAME, RawInputUtil.create(CONTENT_NEW)))
        .isEqualTo(RefUpdate.Result.FORCED);
    edit = editUtil.byChange(change);
    EditInfo info = toEditInfo(false);
    assertThat(info.commit.commit).isEqualTo(edit.get().getRevision().get());
    assertThat(info.commit.parents).hasSize(1);

    edit = editUtil.byChange(change);
    editUtil.delete(edit.get());

    adminRestSession.get(urlEdit()).assertNoContent();
  }

  @Test
  public void retrieveFilesInEdit() throws Exception {
    assertThat(modifier.createEdit(change, ps)).isEqualTo(RefUpdate.Result.NEW);
    Optional<ChangeEdit> edit = editUtil.byChange(change);
    assertThat(modifier.modifyFile(edit.get(), FILE_NAME, RawInputUtil.create(CONTENT_NEW)))
        .isEqualTo(RefUpdate.Result.FORCED);

    EditInfo info = toEditInfo(true);
    assertThat(info.files).hasSize(2);
    List<String> l = Lists.newArrayList(info.files.keySet());
    assertThat(l.get(0)).isEqualTo("/COMMIT_MSG");
    assertThat(l.get(1)).isEqualTo("foo");
  }

  @Test
  public void deleteExistingFile() throws Exception {
    assertThat(modifier.createEdit(change, ps)).isEqualTo(RefUpdate.Result.NEW);
    Optional<ChangeEdit> edit = editUtil.byChange(change);
    assertThat(modifier.deleteFile(edit.get(), FILE_NAME)).isEqualTo(
        RefUpdate.Result.FORCED);
    edit = editUtil.byChange(change);
    exception.expect(ResourceNotFoundException.class);
    fileUtil.getContent(projectCache.get(edit.get().getChange().getProject()),
        ObjectId.fromString(edit.get().getRevision().get()), FILE_NAME);
  }

  @Test
  public void renameExistingFile() throws Exception {
    assertThat(modifier.createEdit(change, ps)).isEqualTo(RefUpdate.Result.NEW);
    Optional<ChangeEdit> edit = editUtil.byChange(change);
    assertThat(modifier.renameFile(edit.get(), FILE_NAME, FILE_NAME3))
        .isEqualTo(RefUpdate.Result.FORCED);
    edit = editUtil.byChange(change);
    assertByteArray(fileUtil.getContent(projectCache.get(edit.get().getChange().getProject()),
        ObjectId.fromString(edit.get().getRevision().get()), FILE_NAME3), CONTENT_OLD);
    exception.expect(ResourceNotFoundException.class);
    fileUtil.getContent(projectCache.get(edit.get().getChange().getProject()),
        ObjectId.fromString(edit.get().getRevision().get()), FILE_NAME);
  }

  @Test
  public void createEditByDeletingExistingFileRest() throws Exception {
    adminRestSession.delete(urlEditFile()).assertNoContent();
    Optional<ChangeEdit> edit = editUtil.byChange(change);
    exception.expect(ResourceNotFoundException.class);
    fileUtil.getContent(projectCache.get(edit.get().getChange().getProject()),
        ObjectId.fromString(edit.get().getRevision().get()), FILE_NAME);
  }

  @Test
  public void deletingNonExistingEditRest() throws Exception {
    adminRestSession.delete(urlEdit()).assertNotFound();
  }

  @Test
  public void deleteExistingFileRest() throws Exception {
    assertThat(modifier.createEdit(change, ps)).isEqualTo(RefUpdate.Result.NEW);
    adminRestSession.delete(urlEditFile()).assertNoContent();
    Optional<ChangeEdit> edit = editUtil.byChange(change);
    exception.expect(ResourceNotFoundException.class);
    fileUtil.getContent(projectCache.get(edit.get().getChange().getProject()),
        ObjectId.fromString(edit.get().getRevision().get()), FILE_NAME);
  }

  @Test
  public void restoreDeletedFileInPatchSet() throws Exception {
    assertThat(modifier.createEdit(change2, ps2)).isEqualTo(
        RefUpdate.Result.NEW);
    Optional<ChangeEdit> edit = editUtil.byChange(change2);
    assertThat(modifier.restoreFile(edit.get(), FILE_NAME)).isEqualTo(
        RefUpdate.Result.FORCED);
    edit = editUtil.byChange(change2);
    assertByteArray(fileUtil.getContent(projectCache.get(edit.get().getChange().getProject()),
        ObjectId.fromString(edit.get().getRevision().get()), FILE_NAME), CONTENT_OLD);
  }

  @Test
  public void revertChanges() throws Exception {
    assertThat(modifier.createEdit(change2, ps2)).isEqualTo(
        RefUpdate.Result.NEW);
    Optional<ChangeEdit> edit = editUtil.byChange(change2);
    assertThat(modifier.restoreFile(edit.get(), FILE_NAME)).isEqualTo(
        RefUpdate.Result.FORCED);
    edit = editUtil.byChange(change2);
    assertByteArray(fileUtil.getContent(projectCache.get(edit.get().getChange().getProject()),
        ObjectId.fromString(edit.get().getRevision().get()), FILE_NAME), CONTENT_OLD);
    assertThat(
        modifier.modifyFile(editUtil.byChange(change2).get(), FILE_NAME,
            RawInputUtil.create(CONTENT_NEW))).isEqualTo(RefUpdate.Result.FORCED);
    edit = editUtil.byChange(change2);
    assertByteArray(fileUtil.getContent(projectCache.get(edit.get().getChange().getProject()),
        ObjectId.fromString(edit.get().getRevision().get()), FILE_NAME), CONTENT_NEW);
    assertThat(modifier.restoreFile(edit.get(), FILE_NAME)).isEqualTo(
        RefUpdate.Result.FORCED);
    edit = editUtil.byChange(change2);
    assertByteArray(fileUtil.getContent(projectCache.get(edit.get().getChange().getProject()),
        ObjectId.fromString(edit.get().getRevision().get()), FILE_NAME), CONTENT_OLD);
    editUtil.delete(edit.get());
  }

  @Test
  public void renameFileRest() throws Exception {
    assertThat(modifier.createEdit(change, ps)).isEqualTo(RefUpdate.Result.NEW);
    Post.Input in = new Post.Input();
    in.oldPath = FILE_NAME;
    in.newPath = FILE_NAME3;
    adminRestSession.post(urlEdit(), in).assertNoContent();
    Optional<ChangeEdit> edit = editUtil.byChange(change);
    assertByteArray(fileUtil.getContent(projectCache.get(edit.get().getChange().getProject()),
        ObjectId.fromString(edit.get().getRevision().get()), FILE_NAME3), CONTENT_OLD);
    exception.expect(ResourceNotFoundException.class);
    fileUtil.getContent(projectCache.get(edit.get().getChange().getProject()),
        ObjectId.fromString(edit.get().getRevision().get()), FILE_NAME);
  }

  @Test
  public void restoreDeletedFileInPatchSetRest() throws Exception {
    Post.Input in = new Post.Input();
    in.restorePath = FILE_NAME;
    adminRestSession.post(urlEdit2(), in).assertNoContent();
    Optional<ChangeEdit> edit = editUtil.byChange(change2);
    assertByteArray(fileUtil.getContent(projectCache.get(edit.get().getChange().getProject()),
        ObjectId.fromString(edit.get().getRevision().get()), FILE_NAME), CONTENT_OLD);
  }

  @Test
  public void amendExistingFile() throws Exception {
    assertThat(modifier.createEdit(change, ps)).isEqualTo(RefUpdate.Result.NEW);
    Optional<ChangeEdit> edit = editUtil.byChange(change);
    assertThat(modifier.modifyFile(edit.get(), FILE_NAME, RawInputUtil.create(CONTENT_NEW)))
        .isEqualTo(RefUpdate.Result.FORCED);
    edit = editUtil.byChange(change);
    assertByteArray(fileUtil.getContent(projectCache.get(edit.get().getChange().getProject()),
        ObjectId.fromString(edit.get().getRevision().get()), FILE_NAME), CONTENT_NEW);
    assertThat(modifier.modifyFile(edit.get(), FILE_NAME, RawInputUtil.create(CONTENT_NEW2)))
        .isEqualTo(RefUpdate.Result.FORCED);
    edit = editUtil.byChange(change);
    assertByteArray(fileUtil.getContent(projectCache.get(edit.get().getChange().getProject()),
        ObjectId.fromString(edit.get().getRevision().get()), FILE_NAME), CONTENT_NEW2);
  }

  @Test
  public void createAndChangeEditInOneRequestRest() throws Exception {
    Put.Input in = new Put.Input();
    in.content = RawInputUtil.create(CONTENT_NEW);
    adminRestSession.putRaw(urlEditFile(), in.content).assertNoContent();
    Optional<ChangeEdit> edit = editUtil.byChange(change);
    assertByteArray(fileUtil.getContent(projectCache.get(edit.get().getChange().getProject()),
        ObjectId.fromString(edit.get().getRevision().get()), FILE_NAME), CONTENT_NEW);
    in.content = RawInputUtil.create(CONTENT_NEW2);
    adminRestSession.putRaw(urlEditFile(), in.content).assertNoContent();
    edit = editUtil.byChange(change);
    assertByteArray(fileUtil.getContent(projectCache.get(edit.get().getChange().getProject()),
        ObjectId.fromString(edit.get().getRevision().get()), FILE_NAME), CONTENT_NEW2);
  }

  @Test
  public void changeEditRest() throws Exception {
    assertThat(modifier.createEdit(change, ps)).isEqualTo(RefUpdate.Result.NEW);
    Put.Input in = new Put.Input();
    in.content = RawInputUtil.create(CONTENT_NEW);
    adminRestSession.putRaw(urlEditFile(), in.content).assertNoContent();
    Optional<ChangeEdit> edit = editUtil.byChange(change);
    assertByteArray(fileUtil.getContent(projectCache.get(edit.get().getChange().getProject()),
        ObjectId.fromString(edit.get().getRevision().get()), FILE_NAME), CONTENT_NEW);
  }

  @Test
  public void emptyPutRequest() throws Exception {
    assertThat(modifier.createEdit(change, ps)).isEqualTo(RefUpdate.Result.NEW);
    adminRestSession.put(urlEditFile()).assertNoContent();
    Optional<ChangeEdit> edit = editUtil.byChange(change);
    assertByteArray(fileUtil.getContent(projectCache.get(edit.get().getChange().getProject()),
        ObjectId.fromString(edit.get().getRevision().get()), FILE_NAME), "".getBytes());
  }

  @Test
  public void createEmptyEditRest() throws Exception {
    adminRestSession.post(urlEdit()).assertNoContent();
    Optional<ChangeEdit> edit = editUtil.byChange(change);
    assertByteArray(fileUtil.getContent(projectCache.get(edit.get().getChange().getProject()),
        ObjectId.fromString(edit.get().getRevision().get()), FILE_NAME), CONTENT_OLD);
  }

  @Test
  public void getFileContentRest() throws Exception {
    Put.Input in = new Put.Input();
    in.content = RawInputUtil.create(CONTENT_NEW);
    adminRestSession.putRaw(urlEditFile(), in.content).assertNoContent();
    Optional<ChangeEdit> edit = editUtil.byChange(change);
    assertThat(modifier.modifyFile(edit.get(), FILE_NAME, RawInputUtil.create(CONTENT_NEW2)))
        .isEqualTo(RefUpdate.Result.FORCED);
    edit = editUtil.byChange(change);
    RestResponse r = adminRestSession.getJsonAccept(urlEditFile());
    r.assertOK();
    assertThat(readContentFromJson(r)).isEqualTo(
        StringUtils.newStringUtf8(CONTENT_NEW2));

    r = adminRestSession.getJsonAccept(urlEditFile(true));
    r.assertOK();
    assertThat(readContentFromJson(r)).isEqualTo(
        StringUtils.newStringUtf8(CONTENT_OLD));
  }

  @Test
  public void getFileNotFoundRest() throws Exception {
    assertThat(modifier.createEdit(change, ps)).isEqualTo(RefUpdate.Result.NEW);
    adminRestSession.delete(urlEditFile()).assertNoContent();
    Optional<ChangeEdit> edit = editUtil.byChange(change);
    adminRestSession.get(urlEditFile()).assertNoContent();
    exception.expect(ResourceNotFoundException.class);
    fileUtil.getContent(projectCache.get(edit.get().getChange().getProject()),
        ObjectId.fromString(edit.get().getRevision().get()), FILE_NAME);
  }

  @Test
  public void addNewFile() throws Exception {
    assertThat(modifier.createEdit(change, ps)).isEqualTo(RefUpdate.Result.NEW);
    Optional<ChangeEdit> edit = editUtil.byChange(change);
    assertThat(modifier.modifyFile(edit.get(), FILE_NAME2, RawInputUtil.create(CONTENT_NEW)))
        .isEqualTo(RefUpdate.Result.FORCED);
    edit = editUtil.byChange(change);
    assertByteArray(fileUtil.getContent(projectCache.get(edit.get().getChange().getProject()),
        ObjectId.fromString(edit.get().getRevision().get()), FILE_NAME2), CONTENT_NEW);
  }

  @Test
  public void addNewFileAndAmend() throws Exception {
    assertThat(modifier.createEdit(change, ps)).isEqualTo(RefUpdate.Result.NEW);
    Optional<ChangeEdit> edit = editUtil.byChange(change);
    assertThat(modifier.modifyFile(edit.get(), FILE_NAME2, RawInputUtil.create(CONTENT_NEW)))
        .isEqualTo(RefUpdate.Result.FORCED);
    edit = editUtil.byChange(change);
    assertByteArray(fileUtil.getContent(projectCache.get(edit.get().getChange().getProject()),
        ObjectId.fromString(edit.get().getRevision().get()), FILE_NAME2), CONTENT_NEW);
    assertThat(modifier.modifyFile(edit.get(), FILE_NAME2, RawInputUtil.create(CONTENT_NEW2)))
        .isEqualTo(RefUpdate.Result.FORCED);
    edit = editUtil.byChange(change);
    assertByteArray(fileUtil.getContent(projectCache.get(edit.get().getChange().getProject()),
        ObjectId.fromString(edit.get().getRevision().get()), FILE_NAME2), CONTENT_NEW2);
  }

  @Test
  public void writeNoChanges() throws Exception {
    assertThat(modifier.createEdit(change, ps)).isEqualTo(RefUpdate.Result.NEW);
    exception.expect(InvalidChangeOperationException.class);
    exception.expectMessage("no changes were made");
    modifier.modifyFile(
        editUtil.byChange(change).get(),
        FILE_NAME,
        RawInputUtil.create(CONTENT_OLD));
  }

  @Test
  public void editCommitMessageCopiesLabelScores() throws Exception {
    String cr = "Code-Review";
    ProjectConfig cfg = projectCache.checkedGet(project).getConfig();
    LabelType codeReview = Util.codeReview();
    codeReview.setCopyAllScoresIfNoCodeChange(true);
    cfg.getLabelSections().put(cr, codeReview);
    saveProjectConfig(project, cfg);

    String changeId = change.getKey().get();
    ReviewInput r = new ReviewInput();
    r.labels = ImmutableMap.<String, Short> of(cr, (short) 1);
    gApi.changes()
        .id(changeId)
        .revision(change.currentPatchSetId().get())
        .review(r);

    assertThat(modifier.createEdit(change, getCurrentPatchSet(changeId)))
        .isEqualTo(RefUpdate.Result.NEW);
    Optional<ChangeEdit> edit = editUtil.byChange(change);
    String newSubj = "New commit message";
    String newMsg = newSubj + "\n\nChange-Id: " + changeId + "\n";
    assertThat(modifier.modifyMessage(edit.get(), newMsg))
        .isEqualTo(RefUpdate.Result.FORCED);
    edit = editUtil.byChange(change);
    editUtil.publish(edit.get());

    ChangeInfo info = get(changeId);
    assertThat(info.subject).isEqualTo(newSubj);
    List<ApprovalInfo> approvals = info.labels.get(cr).all;
    assertThat(approvals).hasSize(1);
    assertThat(approvals.get(0).value).isEqualTo(1);
  }

  @Test
  public void testHasEditPredicate() throws Exception {
    assertThat(modifier.createEdit(change, ps)).isEqualTo(RefUpdate.Result.NEW);
    assertThat(queryEdits()).hasSize(1);

    PatchSet current = getCurrentPatchSet(changeId2);
    assertThat(modifier.createEdit(change2, current)).isEqualTo(RefUpdate.Result.NEW);
    assertThat(
        modifier.modifyFile(editUtil.byChange(change2).get(), FILE_NAME,
            RawInputUtil.create(CONTENT_NEW))).isEqualTo(RefUpdate.Result.FORCED);
    assertThat(queryEdits()).hasSize(2);

    assertThat(
        modifier.modifyFile(editUtil.byChange(change).get(), FILE_NAME,
            RawInputUtil.create(CONTENT_NEW))).isEqualTo(RefUpdate.Result.FORCED);
    editUtil.delete(editUtil.byChange(change).get());
    assertThat(queryEdits()).hasSize(1);

    editUtil.publish(editUtil.byChange(change2).get());
    assertThat(queryEdits()).hasSize(0);

    setApiUser(user);
    assertThat(modifier.createEdit(change, ps)).isEqualTo(RefUpdate.Result.NEW);
    assertThat(queryEdits()).hasSize(1);

    setApiUser(admin);
    assertThat(queryEdits()).hasSize(0);
  }

  @Test
  public void files() throws Exception {
    assertThat(modifier.createEdit(change, ps)).isEqualTo(RefUpdate.Result.NEW);
    ChangeEdit edit = editUtil.byChange(change).get();
    assertThat(modifier.modifyFile(edit, FILE_NAME, RawInputUtil.create(CONTENT_NEW)))
        .isEqualTo(RefUpdate.Result.FORCED);
    edit = editUtil.byChange(change).get();

    RestResponse r = adminRestSession.getJsonAccept(urlRevisionFiles(edit));
    Map<String, FileInfo> files = readContentFromJson(
        r, new TypeToken<Map<String, FileInfo>>() {});
    assertThat(files).containsKey(FILE_NAME);

    r = adminRestSession.getJsonAccept(urlRevisionFiles());
    files = readContentFromJson(r, new TypeToken<Map<String, FileInfo>>() {});
    assertThat(files).containsKey(FILE_NAME);
  }

  @Test
  public void diff() throws Exception {
    assertThat(modifier.createEdit(change, ps)).isEqualTo(RefUpdate.Result.NEW);
    ChangeEdit edit = editUtil.byChange(change).get();
    assertThat(modifier.modifyFile(edit, FILE_NAME, RawInputUtil.create(CONTENT_NEW)))
        .isEqualTo(RefUpdate.Result.FORCED);
    edit = editUtil.byChange(change).get();

    RestResponse r = adminRestSession.getJsonAccept(urlDiff(edit));
    DiffInfo diff = readContentFromJson(r, DiffInfo.class);
    assertThat(diff.diffHeader.get(0)).contains(FILE_NAME);

    r = adminRestSession.getJsonAccept(urlDiff());
    diff = readContentFromJson(r, DiffInfo.class);
    assertThat(diff.diffHeader.get(0)).contains(FILE_NAME);
  }

  @Test
  public void createEditWithoutPushPatchSetPermission() throws Exception {
    // Create new project with clean permissions
    Project.NameKey p = createProject("addPatchSetEdit");
    // Clone repository as user
    TestRepository<InMemoryRepository> userTestRepo =
        cloneProject(p, user);

    // Block default permission
    block(Permission.ADD_PATCH_SET, REGISTERED_USERS, "refs/for/*", p);

    // Create change as user
    PushOneCommit push = pushFactory.create(
        db, user.getIdent(), userTestRepo);
    PushOneCommit.Result r1 = push.to("refs/for/master");
    r1.assertOkStatus();

    // Try to create edit as admin
    assertThat(modifier.createEdit(r1.getChange().change(),
        r1.getPatchSet())).isEqualTo(RefUpdate.Result.REJECTED);
  }

  private List<ChangeInfo> queryEdits() throws Exception {
    return query("project:{" + project.get() + "} has:edit");
  }

  private String newChange(PersonIdent ident) throws Exception {
    PushOneCommit push =
        pushFactory.create(db, ident, testRepo, PushOneCommit.SUBJECT, FILE_NAME,
            new String(CONTENT_OLD, UTF_8));
    return push.to("refs/for/master").getChangeId();
  }

  private String amendChange(PersonIdent ident, String changeId) throws Exception {
    PushOneCommit push =
        pushFactory.create(db, ident, testRepo, PushOneCommit.SUBJECT, FILE_NAME2,
            new String(CONTENT_NEW2, UTF_8), changeId);
    return push.to("refs/for/master").getChangeId();
  }

  private String newChange2(PersonIdent ident) throws Exception {
    PushOneCommit push =
        pushFactory.create(db, ident, testRepo, PushOneCommit.SUBJECT, FILE_NAME,
            new String(CONTENT_OLD, UTF_8));
    return push.rm("refs/for/master").getChangeId();
  }

  private Change getChange(String changeId) throws Exception {
    return getOnlyElement(queryProvider.get().byKeyPrefix(changeId)).change();
  }

  private PatchSet getCurrentPatchSet(String changeId) throws Exception {
    return getOnlyElement(queryProvider.get().byKeyPrefix(changeId))
        .currentPatchSet();
  }

  private static void assertByteArray(BinaryResult result, byte[] expected)
        throws Exception {
    ByteArrayOutputStream os = new ByteArrayOutputStream();
    result.writeTo(os);
    assertThat(os.toByteArray()).isEqualTo(expected);
  }

  private String urlEdit() {
    return "/changes/"
        + change.getChangeId()
        + "/edit";
  }

  private String urlEdit2() {
    return "/changes/"
        + change2.getChangeId()
        + "/edit/";
  }

  private String urlEditMessage(boolean base) {
    return "/changes/"
        + change.getChangeId()
        + "/edit:message"
        + (base ? "?base" : "");
  }

  private String urlEditFile() {
    return urlEditFile(false);
  }

  private String urlEditFile(boolean base) {
    return urlEdit()
        + "/"
        + FILE_NAME
        + (base ? "?base" : "");
  }

  private String urlGetFiles() {
    return urlEdit()
        + "?list";
  }

  private String urlRevisionFiles(ChangeEdit edit) {
    return "/changes/"
      + change.getChangeId()
      + "/revisions/"
      + edit.getRevision().get()
      + "/files";
  }

  private String urlRevisionFiles() {
    return "/changes/"
      + change.getChangeId()
      + "/revisions/0/files";
  }

  private String urlPublish() {
    return "/changes/"
        + change.getChangeId()
        + "/edit:publish";
  }

  private String urlRebase() {
    return "/changes/"
        + change.getChangeId()
        + "/edit:rebase";
  }

  private String urlDiff() {
    return "/changes/"
        + change.getChangeId()
        + "/revisions/0/files/"
        + FILE_NAME
        + "/diff?context=ALL&intraline";
  }

  private String urlDiff(ChangeEdit edit) {
    return "/changes/"
        + change.getChangeId()
        + "/revisions/"
        + edit.getRevision().get()
        + "/files/"
        + FILE_NAME
        + "/diff?context=ALL&intraline";
  }

  private EditInfo toEditInfo(boolean files) throws Exception {
    RestResponse r = adminRestSession.get(files ? urlGetFiles() : urlEdit());
    return readContentFromJson(r, EditInfo.class);
  }

  private <T> T readContentFromJson(RestResponse r, Class<T> clazz)
      throws Exception {
    r.assertOK();
    JsonReader jsonReader = new JsonReader(r.getReader());
    jsonReader.setLenient(true);
    return newGson().fromJson(jsonReader, clazz);
  }

  private <T> T readContentFromJson(RestResponse r, TypeToken<T> typeToken)
      throws Exception {
    r.assertOK();
    JsonReader jsonReader = new JsonReader(r.getReader());
    jsonReader.setLenient(true);
    return newGson().fromJson(jsonReader, typeToken.getType());
  }

  private String readContentFromJson(RestResponse r) throws Exception {
    return readContentFromJson(r, String.class);
  }

  private void assertChangeMessages(Change c, List<String> expectedMessages)
      throws Exception {
    ChangeInfo ci = get(c.getId().toString());
    assertThat(ci.messages).isNotNull();
    assertThat(ci.messages).hasSize(expectedMessages.size());
    List<String> actualMessages = new ArrayList<>();
    Iterator<ChangeMessageInfo> it = ci.messages.iterator();
    while (it.hasNext()) {
      actualMessages.add(it.next().message);
    }
    assertThat(actualMessages)
      .containsExactlyElementsIn(expectedMessages)
      .inOrder();
  }
}
