blob: b9ef0bf48e6e0df8bd2d3771386ab1ec65e0935f [file] [log] [blame]
// Copyright (C) 2022 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.api.revision;
import static com.google.common.truth.Truth.assertThat;
import static com.google.gerrit.acceptance.testsuite.project.TestProjectUpdate.block;
import static com.google.gerrit.extensions.common.testing.EditInfoSubject.assertThat;
import static com.google.gerrit.server.group.SystemGroupBackend.ANONYMOUS_USERS;
import static com.google.gerrit.server.group.SystemGroupBackend.REGISTERED_USERS;
import static com.google.gerrit.testing.GerritJUnit.assertThrows;
import com.google.common.collect.ImmutableMap;
import com.google.gerrit.acceptance.AbstractDaemonTest;
import com.google.gerrit.acceptance.PushOneCommit;
import com.google.gerrit.acceptance.RestResponse;
import com.google.gerrit.acceptance.testsuite.account.AccountOperations;
import com.google.gerrit.acceptance.testsuite.change.ChangeOperations;
import com.google.gerrit.acceptance.testsuite.project.ProjectOperations;
import com.google.gerrit.acceptance.testsuite.request.RequestScopeOperations;
import com.google.gerrit.entities.Account;
import com.google.gerrit.entities.Change;
import com.google.gerrit.entities.Patch;
import com.google.gerrit.entities.Permission;
import com.google.gerrit.entities.RefNames;
import com.google.gerrit.extensions.api.changes.PublishChangeEditInput;
import com.google.gerrit.extensions.api.changes.ReviewResult;
import com.google.gerrit.extensions.client.Comment;
import com.google.gerrit.extensions.common.ApplyProvidedFixInput;
import com.google.gerrit.extensions.common.ChangeInfo;
import com.google.gerrit.extensions.common.EditInfo;
import com.google.gerrit.extensions.common.FixReplacementInfo;
import com.google.gerrit.extensions.common.RevisionInfo;
import com.google.gerrit.extensions.restapi.BadRequestException;
import com.google.gerrit.extensions.restapi.BinaryResult;
import com.google.gerrit.extensions.restapi.ResourceConflictException;
import com.google.gerrit.extensions.restapi.ResourceNotFoundException;
import com.google.gerrit.extensions.restapi.testing.BinaryResultSubject;
import com.google.gson.stream.JsonReader;
import com.google.inject.Inject;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import org.junit.Before;
import org.junit.Test;
public class ApplyProvidedFixIT extends AbstractDaemonTest {
@Inject private ProjectOperations projectOperations;
@Inject private AccountOperations accountOperations;
@Inject private ChangeOperations changeOperations;
@Inject private RequestScopeOperations requestScopeOperations;
private static final String FILE_NAME = "file_to_fix.txt";
private static final String FILE_NAME2 = "another_file_to_fix.txt";
private static final String FILE_NAME3 = "file_without_newline_at_end.txt";
private static final String FILE_CONTENT =
"First line\nSecond line\nThird line\nFourth line\nFifth line\nSixth line"
+ "\nSeventh line\nEighth line\nNinth line\nTenth line\n";
private static final String FILE_CONTENT2 = "1st line\n2nd line\n3rd line\n";
private static final String FILE_CONTENT3 = "1st line\n2nd line";
private String changeId;
private String commitId;
@Before
public void setUp() throws Exception {
PushOneCommit push =
pushFactory.create(
admin.newIdent(),
testRepo,
"Provide files which can be used for fixes",
ImmutableMap.of(
FILE_NAME, FILE_CONTENT, FILE_NAME2, FILE_CONTENT2, FILE_NAME3, FILE_CONTENT3));
PushOneCommit.Result changeResult = push.to("refs/for/master");
changeId = changeResult.getChangeId();
commitId = changeResult.getCommit().getName();
}
@Test
public void applyProvidedFixWithinALineCanBeApplied() throws Exception {
ApplyProvidedFixInput applyProvidedFixInput =
createApplyProvidedFixInput(FILE_NAME, "Modified content", 3, 1, 3, 3);
gApi.changes().id(changeId).current().applyFix(applyProvidedFixInput);
Optional<BinaryResult> file = gApi.changes().id(changeId).edit().getFile(FILE_NAME);
BinaryResultSubject.assertThat(file)
.value()
.asString()
.isEqualTo(
"First line\nSecond line\nTModified contentrd line\nFourth line\nFifth line\n"
+ "Sixth line\nSeventh line\nEighth line\nNinth line\nTenth line\n");
}
@Test
public void applyProvidedFixAfterUpdatingPreferredEmail() throws Exception {
String emailOne = "email1@example.com";
Account.Id testUser = accountOperations.newAccount().preferredEmail(emailOne).create();
// Create change
Change.Id change =
changeOperations
.newChange()
.project(project)
.file(FILE_NAME)
.content(FILE_CONTENT)
.owner(testUser)
.create();
// Change preferred email for the user
String emailTwo = "email2@example.com";
accountOperations.account(testUser).forUpdate().preferredEmail(emailTwo).update();
requestScopeOperations.setApiUser(testUser);
// Apply fix
ApplyProvidedFixInput applyProvidedFixInput =
createApplyProvidedFixInput(FILE_NAME, "Modified content", 3, 1, 3, 3);
gApi.changes().id(change.get()).current().applyFix(applyProvidedFixInput);
EditInfo editInfo = gApi.changes().id(change.get()).edit().get().orElseThrow();
assertThat(editInfo.commit.committer.email).isEqualTo(emailOne);
}
@Test
public void applyProvidedFixRestAPItestForASimpleFix() throws Exception {
ApplyProvidedFixInput applyProvidedFixInput =
createApplyProvidedFixInput(FILE_NAME, "Modified content", 3, 1, 3, 3);
RestResponse resp =
adminRestSession.post(
"/changes/" + changeId + "/revisions/" + commitId + "/fix:apply",
applyProvidedFixInput);
readContentFromJson(resp, 200, ReviewResult.class);
Optional<BinaryResult> file = gApi.changes().id(changeId).edit().getFile(FILE_NAME);
BinaryResultSubject.assertThat(file)
.value()
.asString()
.isEqualTo(
"First line\nSecond line\nTModified contentrd line\nFourth line\nFifth line\n"
+ "Sixth line\nSeventh line\nEighth line\nNinth line\nTenth line\n");
}
@Test
public void applyProvidedFixSpanningMultipleLinesCanBeApplied() throws Exception {
ApplyProvidedFixInput applyProvidedFixInput =
createApplyProvidedFixInput(FILE_NAME, "Modified content\n5", 3, 2, 5, 3);
gApi.changes().id(changeId).current().applyFix(applyProvidedFixInput);
Optional<BinaryResult> file = gApi.changes().id(changeId).edit().getFile(FILE_NAME);
BinaryResultSubject.assertThat(file)
.value()
.asString()
.isEqualTo(
"First line\nSecond line\nThModified content\n5th line\nSixth line\nSeventh line\n"
+ "Eighth line\nNinth line\nTenth line\n");
}
@Test
public void applyProvidedFixWithTwoCloseReplacementsOnSameFileCanBeApplied() throws Exception {
FixReplacementInfo fixReplacementInfo1 = new FixReplacementInfo();
fixReplacementInfo1.path = FILE_NAME;
fixReplacementInfo1.range = createRange(2, 0, 3, 0);
fixReplacementInfo1.replacement = "First modification\n";
FixReplacementInfo fixReplacementInfo2 = new FixReplacementInfo();
fixReplacementInfo2.path = FILE_NAME;
fixReplacementInfo2.range = createRange(3, 0, 4, 0);
fixReplacementInfo2.replacement = "Some other modified content\n";
List<FixReplacementInfo> fixReplacementInfoList =
Arrays.asList(fixReplacementInfo1, fixReplacementInfo2);
ApplyProvidedFixInput applyProvidedFixInput = new ApplyProvidedFixInput();
applyProvidedFixInput.fixReplacementInfos = fixReplacementInfoList;
gApi.changes().id(changeId).current().applyFix(applyProvidedFixInput);
Optional<BinaryResult> file = gApi.changes().id(changeId).edit().getFile(FILE_NAME);
BinaryResultSubject.assertThat(file)
.value()
.asString()
.isEqualTo(
"First line\nFirst modification\nSome other modified content\nFourth line\nFifth line\n"
+ "Sixth line\nSeventh line\nEighth line\nNinth line\nTenth line\n");
}
@Test
public void twoApplyProvidedFixesOnSameFileCanBeApplied() throws Exception {
FixReplacementInfo fixReplacementInfo1 = new FixReplacementInfo();
fixReplacementInfo1.path = FILE_NAME;
fixReplacementInfo1.range = createRange(2, 0, 3, 0);
fixReplacementInfo1.replacement = "First modification\n";
FixReplacementInfo fixReplacementInfo2 = new FixReplacementInfo();
fixReplacementInfo2.path = FILE_NAME;
fixReplacementInfo2.range = createRange(8, 0, 9, 0);
fixReplacementInfo2.replacement = "Some other modified content\n";
List<FixReplacementInfo> fixReplacementInfoList =
Arrays.asList(fixReplacementInfo1, fixReplacementInfo2);
ApplyProvidedFixInput applyProvidedFixInput = new ApplyProvidedFixInput();
applyProvidedFixInput.fixReplacementInfos = fixReplacementInfoList;
gApi.changes().id(changeId).current().applyFix(applyProvidedFixInput);
Optional<BinaryResult> file = gApi.changes().id(changeId).edit().getFile(FILE_NAME);
BinaryResultSubject.assertThat(file)
.value()
.asString()
.isEqualTo(
"First line\nFirst modification\nThird line\nFourth line\nFifth line\nSixth line\n"
+ "Seventh line\nSome other modified content\nNinth line\nTenth line\n");
}
@Test
public void twoConflictingApplyProvidedFixesOnSameFileCannotBeApplied() throws Exception {
FixReplacementInfo fixReplacementInfo1 = new FixReplacementInfo();
fixReplacementInfo1.path = FILE_NAME;
fixReplacementInfo1.range = createRange(2, 0, 3, 1);
fixReplacementInfo1.replacement = "First modification\n";
FixReplacementInfo fixReplacementInfo2 = new FixReplacementInfo();
fixReplacementInfo2.path = FILE_NAME;
fixReplacementInfo2.range = createRange(3, 0, 4, 0);
fixReplacementInfo2.replacement = "Some other modified content\n";
List<FixReplacementInfo> fixReplacementInfoList =
Arrays.asList(fixReplacementInfo1, fixReplacementInfo2);
ApplyProvidedFixInput applyProvidedFixInput = new ApplyProvidedFixInput();
applyProvidedFixInput.fixReplacementInfos = fixReplacementInfoList;
ResourceConflictException thrown =
assertThrows(
ResourceConflictException.class,
() -> gApi.changes().id(changeId).current().applyFix(applyProvidedFixInput));
assertThat(thrown).hasMessageThat().contains("Cannot calculate fix replacement");
}
@Test
public void applyProvidedFixInvolvingTwoFilesCanBeApplied() throws Exception {
FixReplacementInfo fixReplacementInfo1 = new FixReplacementInfo();
fixReplacementInfo1.path = FILE_NAME;
fixReplacementInfo1.range = createRange(2, 0, 3, 0);
fixReplacementInfo1.replacement = "First modification\n";
FixReplacementInfo fixReplacementInfo2 = new FixReplacementInfo();
fixReplacementInfo2.path = FILE_NAME2;
fixReplacementInfo2.range = createRange(1, 0, 2, 0);
fixReplacementInfo2.replacement = "Different file modification\n";
List<FixReplacementInfo> fixReplacementInfoList =
Arrays.asList(fixReplacementInfo1, fixReplacementInfo2);
ApplyProvidedFixInput applyProvidedFixInput = new ApplyProvidedFixInput();
applyProvidedFixInput.fixReplacementInfos = fixReplacementInfoList;
gApi.changes().id(changeId).current().applyFix(applyProvidedFixInput);
Optional<BinaryResult> file = gApi.changes().id(changeId).edit().getFile(FILE_NAME);
BinaryResultSubject.assertThat(file)
.value()
.asString()
.isEqualTo(
"First line\nFirst modification\nThird line\nFourth line\nFifth line\nSixth line\n"
+ "Seventh line\nEighth line\nNinth line\nTenth line\n");
Optional<BinaryResult> file2 = gApi.changes().id(changeId).edit().getFile(FILE_NAME2);
BinaryResultSubject.assertThat(file2)
.value()
.asString()
.isEqualTo("Different file modification\n2nd line\n3rd line\n");
}
@Test
public void applyProvidedFixReferringToNonExistentFileCannotBeApplied() throws Exception {
ApplyProvidedFixInput applyProvidedFixInput =
createApplyProvidedFixInput("a_non_existent_file.txt", "Modified content\n", 1, 0, 2, 0);
assertThrows(
ResourceNotFoundException.class,
() -> gApi.changes().id(changeId).current().applyFix(applyProvidedFixInput));
}
@Test
public void applyProvidedFixRestAPIcallWithoutAddPatchSetPermissionCannotBeApplied()
throws Exception {
ApplyProvidedFixInput applyProvidedFixInput =
createApplyProvidedFixInput(FILE_NAME, "Modified content", 3, 1, 3, 3);
String allRefs = RefNames.REFS + "*";
projectOperations
.project(project)
.forUpdate()
.add(block(Permission.ADD_PATCH_SET).ref(allRefs).group(ANONYMOUS_USERS))
.add(block(Permission.ADD_PATCH_SET).ref(allRefs).group(REGISTERED_USERS))
.update();
RestResponse resp =
userRestSession.post(
"/changes/" + changeId + "/revisions/" + commitId + "/fix:apply",
applyProvidedFixInput);
resp.assertStatus(403);
}
@Test
public void applyProvidedFixOnCurrentPatchSetWithExistingChangeEditCanBeApplied()
throws Exception {
FixReplacementInfo fixReplacementInfo1 = new FixReplacementInfo();
fixReplacementInfo1.path = FILE_NAME;
fixReplacementInfo1.range = createRange(2, 0, 3, 0);
fixReplacementInfo1.replacement = "First modification\n";
List<FixReplacementInfo> fixReplacementInfoList = Arrays.asList(fixReplacementInfo1);
ApplyProvidedFixInput applyProvidedFixInput = new ApplyProvidedFixInput();
applyProvidedFixInput.fixReplacementInfos = fixReplacementInfoList;
// Create an empty change edit.
gApi.changes().id(changeId).edit().create();
gApi.changes().id(changeId).current().applyFix(applyProvidedFixInput);
Optional<BinaryResult> file = gApi.changes().id(changeId).edit().getFile(FILE_NAME);
BinaryResultSubject.assertThat(file)
.value()
.asString()
.isEqualTo(
"First line\nFirst modification\nThird line\nFourth line\nFifth line\nSixth line\n"
+ "Seventh line\nEighth line\nNinth line\nTenth line\n");
}
@Test
public void applyProvidedFixOnPreviousPatchSetCannotBeApplied() throws Exception {
// Remember patch set and add another one.
String previousRevision = gApi.changes().id(changeId).get().currentRevision;
amendChange(changeId);
ApplyProvidedFixInput applyProvidedFixInput =
createApplyProvidedFixInput(FILE_NAME, "Modified content", 3, 1, 3, 3);
ResourceConflictException thrown =
assertThrows(
ResourceConflictException.class,
() ->
gApi.changes()
.id(changeId)
.revision(previousRevision)
.applyFix(applyProvidedFixInput));
assertThat(thrown)
.hasMessageThat()
.contains("A change edit may only be created for the current patch set");
}
@Test
public void applyProvidedFixOnCurrentPatchSetWithChangeEditOnPreviousPatchSetCannotBeApplied()
throws Exception {
// Create an empty change edit.
gApi.changes().id(changeId).edit().create();
// Add another patch set.
amendChange(changeId);
ApplyProvidedFixInput applyProvidedFixInput =
createApplyProvidedFixInput(FILE_NAME, "Modified content", 3, 1, 3, 3);
ResourceConflictException thrown =
assertThrows(
ResourceConflictException.class,
() -> gApi.changes().id(changeId).current().applyFix(applyProvidedFixInput));
assertThat(thrown)
.hasMessageThat()
.contains("on which the existing change edit is based may be modified");
}
@Test
public void applyProvidedFixOnCommitMessageCanBeApplied() throws Exception {
// Set a dedicated commit message.
String footer = "\nChange-Id: " + changeId + "\n";
String originalCommitMessage = "Line 1 of commit message\nLine 2 of commit message\n" + footer;
gApi.changes().id(changeId).edit().modifyCommitMessage(originalCommitMessage);
gApi.changes().id(changeId).edit().publish();
ApplyProvidedFixInput applyProvidedFixInput =
createApplyProvidedFixInput(Patch.COMMIT_MSG, "Modified line\n", 7, 0, 8, 0);
gApi.changes().id(changeId).current().applyFix(applyProvidedFixInput);
String commitMessage = gApi.changes().id(changeId).edit().getCommitMessage();
assertThat(commitMessage).isEqualTo("Modified line\nLine 2 of commit message\n" + footer);
}
@Test
public void applyProvidedFixOnHeaderPartOfCommitMessageCannotBeApplied() throws Exception {
// Set a dedicated commit message.
String footer = "Change-Id: " + changeId;
String originalCommitMessage =
"Line 1 of commit message\nLine 2 of commit message\n" + "\n" + footer + "\n";
gApi.changes().id(changeId).edit().modifyCommitMessage(originalCommitMessage);
gApi.changes().id(changeId).edit().publish();
ApplyProvidedFixInput applyProvidedFixInput =
createApplyProvidedFixInput(Patch.COMMIT_MSG, "Modified line\n", 1, 0, 2, 0);
ResourceConflictException exception =
assertThrows(
ResourceConflictException.class,
() -> gApi.changes().id(changeId).current().applyFix(applyProvidedFixInput));
assertThat(exception).hasMessageThat().contains("header");
}
@Test
public void applyProvidedFixContainingSeveralModificationsOfCommitMessageCanBeApplied()
throws Exception {
// Set a dedicated commit message.
String footer = "\nChange-Id: " + changeId + "\n";
String originalCommitMessage =
"Line 1 of commit message\nLine 2 of commit message\nLine 3 of commit message\n" + footer;
gApi.changes().id(changeId).edit().modifyCommitMessage(originalCommitMessage);
gApi.changes().id(changeId).edit().publish();
FixReplacementInfo fixReplacementInfo1 = new FixReplacementInfo();
fixReplacementInfo1.path = Patch.COMMIT_MSG;
fixReplacementInfo1.range = createRange(7, 0, 8, 0);
fixReplacementInfo1.replacement = "Modified line 1\n";
FixReplacementInfo fixReplacementInfo2 = new FixReplacementInfo();
fixReplacementInfo2.path = Patch.COMMIT_MSG;
fixReplacementInfo2.range = createRange(9, 0, 10, 0);
fixReplacementInfo2.replacement = "Modified line 3\n";
List<FixReplacementInfo> fixReplacementInfoList =
Arrays.asList(fixReplacementInfo1, fixReplacementInfo2);
ApplyProvidedFixInput applyProvidedFixInput = new ApplyProvidedFixInput();
applyProvidedFixInput.fixReplacementInfos = fixReplacementInfoList;
gApi.changes().id(changeId).current().applyFix(applyProvidedFixInput);
String commitMessage = gApi.changes().id(changeId).edit().getCommitMessage();
assertThat(commitMessage)
.isEqualTo("Modified line 1\nLine 2 of commit message\nModified line 3\n" + footer);
}
@Test
public void applyProvidedFixModifyingTheCommitMessageAndAFileCanBeApplied() throws Exception {
// Set a dedicated commit message.
String footer = "\nChange-Id: " + changeId + "\n";
String originalCommitMessage = "Line 1 of commit message\nLine 2 of commit message\n" + footer;
gApi.changes().id(changeId).edit().modifyCommitMessage(originalCommitMessage);
gApi.changes().id(changeId).edit().publish();
FixReplacementInfo fixReplacementInfo1 = new FixReplacementInfo();
fixReplacementInfo1.path = Patch.COMMIT_MSG;
fixReplacementInfo1.range = createRange(7, 0, 8, 0);
fixReplacementInfo1.replacement = "Modified line 1\n";
FixReplacementInfo fixReplacementInfo2 = new FixReplacementInfo();
fixReplacementInfo2.path = FILE_NAME2;
fixReplacementInfo2.range = createRange(1, 0, 2, 0);
fixReplacementInfo2.replacement = "File modification\n";
List<FixReplacementInfo> fixReplacementInfoList =
Arrays.asList(fixReplacementInfo1, fixReplacementInfo2);
ApplyProvidedFixInput applyProvidedFixInput = new ApplyProvidedFixInput();
applyProvidedFixInput.fixReplacementInfos = fixReplacementInfoList;
gApi.changes().id(changeId).current().applyFix(applyProvidedFixInput);
String commitMessage = gApi.changes().id(changeId).edit().getCommitMessage();
assertThat(commitMessage).isEqualTo("Modified line 1\nLine 2 of commit message\n" + footer);
Optional<BinaryResult> file = gApi.changes().id(changeId).edit().getFile(FILE_NAME2);
BinaryResultSubject.assertThat(file)
.value()
.asString()
.isEqualTo("File modification\n2nd line\n3rd line\n");
}
@Test
public void twoApplyProvidedFixesNonOverlappingOnCommitMessageCanBeAppliedSubsequently()
throws Exception {
// Set a dedicated commit message.
String footer = "\nChange-Id: " + changeId + "\n";
String originalCommitMessage =
"Line 1 of commit message\nLine 2 of commit message\nLine 3 of commit message\n" + footer;
gApi.changes().id(changeId).edit().modifyCommitMessage(originalCommitMessage);
gApi.changes().id(changeId).edit().publish();
FixReplacementInfo fixReplacementInfo1 = new FixReplacementInfo();
fixReplacementInfo1.path = Patch.COMMIT_MSG;
fixReplacementInfo1.range = createRange(7, 0, 8, 0);
fixReplacementInfo1.replacement = "Modified line 1\n";
FixReplacementInfo fixReplacementInfo2 = new FixReplacementInfo();
fixReplacementInfo2.path = Patch.COMMIT_MSG;
fixReplacementInfo2.range = createRange(9, 0, 10, 0);
fixReplacementInfo2.replacement = "Modified line 3\n";
List<FixReplacementInfo> fixReplacementInfoList1 = Arrays.asList(fixReplacementInfo1);
ApplyProvidedFixInput applyProvidedFixInput1 = new ApplyProvidedFixInput();
applyProvidedFixInput1.fixReplacementInfos = fixReplacementInfoList1;
List<FixReplacementInfo> fixReplacementInfoList2 = Arrays.asList(fixReplacementInfo2);
ApplyProvidedFixInput applyProvidedFixInput2 = new ApplyProvidedFixInput();
applyProvidedFixInput2.fixReplacementInfos = fixReplacementInfoList2;
gApi.changes().id(changeId).current().applyFix(applyProvidedFixInput1);
gApi.changes().id(changeId).current().applyFix(applyProvidedFixInput2);
String commitMessage = gApi.changes().id(changeId).edit().getCommitMessage();
assertThat(commitMessage)
.isEqualTo("Modified line 1\nLine 2 of commit message\nModified line 3\n" + footer);
}
@Test
public void applyingStoredFixTwiceIsIdempotent() throws Exception {
ApplyProvidedFixInput applyProvidedFixInput =
createApplyProvidedFixInput(FILE_NAME, "Modified content", 3, 1, 3, 3);
gApi.changes().id(changeId).current().applyFix(applyProvidedFixInput);
String expectedEditCommit =
gApi.changes().id(changeId).edit().get().map(edit -> edit.commit.commit).orElse("");
// Apply the fix again.
gApi.changes().id(changeId).current().applyFix(applyProvidedFixInput);
Optional<EditInfo> editInfo = gApi.changes().id(changeId).edit().get();
assertThat(editInfo).value().commit().commit().isEqualTo(expectedEditCommit);
}
@Test
public void applyProvidedFixReturnsEditInfoForCreatedChangeEdit() throws Exception {
ApplyProvidedFixInput applyProvidedFixInput =
createApplyProvidedFixInput(FILE_NAME, "Modified content", 3, 1, 3, 3);
EditInfo editInfo = gApi.changes().id(changeId).current().applyFix(applyProvidedFixInput);
Optional<EditInfo> expectedEditInfo = gApi.changes().id(changeId).edit().get();
String expectedEditCommit = expectedEditInfo.map(edit -> edit.commit.commit).orElse("");
assertThat(editInfo).commit().commit().isEqualTo(expectedEditCommit);
String expectedBaseRevision = expectedEditInfo.map(edit -> edit.baseRevision).orElse("");
assertThat(editInfo).baseRevision().isEqualTo(expectedBaseRevision);
}
@Test
public void createdApplyProvidedFixChangeEditIsBasedOnCurrentPatchSet() throws Exception {
String currentRevision = gApi.changes().id(changeId).get().currentRevision;
ApplyProvidedFixInput applyProvidedFixInput =
createApplyProvidedFixInput(FILE_NAME, "Modified content", 3, 1, 3, 3);
EditInfo editInfo = gApi.changes().id(changeId).current().applyFix(applyProvidedFixInput);
assertThat(editInfo).baseRevision().isEqualTo(currentRevision);
}
@Test
public void applyProvidedFixRestCallWithDifferentUserTheUserBecomesUploader() throws Exception {
ApplyProvidedFixInput applyProvidedFixInput =
createApplyProvidedFixInput(FILE_NAME, "Modified content", 3, 1, 3, 3);
ChangeInfo changeInfo = gApi.changes().id(changeId).get();
RevisionInfo rev = changeInfo.revisions.get(changeInfo.currentRevision);
assertThat(rev.uploader.username).isEqualTo(admin.username());
RestResponse resp =
userRestSession.post(
"/changes/" + changeId + "/revisions/" + commitId + "/fix:apply",
applyProvidedFixInput);
resp.assertStatus(200);
PublishChangeEditInput publishInput = new PublishChangeEditInput();
RestResponse resp2 =
userRestSession.post("/changes/" + changeId + "/edit:publish", publishInput);
resp2.assertStatus(204);
changeInfo = gApi.changes().id(changeId).get();
RevisionInfo rev2 = changeInfo.revisions.get(changeInfo.currentRevision);
assertThat(rev2.uploader.username).isEqualTo(user.username());
}
@Test
public void applyProvidedFixInputNullReturnsBadRequestException() throws Exception {
ApplyProvidedFixInput applyProvidedFixInput = null;
BadRequestException thrown =
assertThrows(
BadRequestException.class,
() -> gApi.changes().id(changeId).current().applyFix(applyProvidedFixInput));
assertThat(thrown).hasMessageThat().contains("applyProvidedFixInput is required");
}
@Test
public void applyProvidedFixInputFixReplacementInfosNullReturnsBadRequestException()
throws Exception {
ApplyProvidedFixInput applyProvidedFixInput = new ApplyProvidedFixInput();
BadRequestException thrown =
assertThrows(
BadRequestException.class,
() -> gApi.changes().id(changeId).current().applyFix(applyProvidedFixInput));
assertThat(thrown)
.hasMessageThat()
.contains("applyProvidedFixInput.fixReplacementInfos is required");
}
private ApplyProvidedFixInput createApplyProvidedFixInput(
String file_name,
String replacement,
int startLine,
int startCharacter,
int endLine,
int endCharacter) {
FixReplacementInfo fixReplacementInfo = new FixReplacementInfo();
fixReplacementInfo.path = file_name;
fixReplacementInfo.replacement = replacement;
fixReplacementInfo.range = createRange(startLine, startCharacter, endLine, endCharacter);
List<FixReplacementInfo> fixReplacementInfoList = Arrays.asList(fixReplacementInfo);
ApplyProvidedFixInput applyProvidedFixInput = new ApplyProvidedFixInput();
applyProvidedFixInput.fixReplacementInfos = fixReplacementInfoList;
return applyProvidedFixInput;
}
private static Comment.Range createRange(
int startLine, int startCharacter, int endLine, int endCharacter) {
Comment.Range range = new Comment.Range();
range.startLine = startLine;
range.startCharacter = startCharacter;
range.endLine = endLine;
range.endCharacter = endCharacter;
return range;
}
private static <T> T readContentFromJson(RestResponse r, int expectedStatus, Class<T> clazz)
throws Exception {
r.assertStatus(expectedStatus);
try (JsonReader jsonReader = new JsonReader(r.getReader())) {
jsonReader.setLenient(true);
return newGson().fromJson(jsonReader, clazz);
}
}
}