blob: 379a712d7ba2528df3a6103b3e5a34a7b561d8bd [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.server.change;
import static com.google.common.collect.ImmutableSet.toImmutableSet;
import static com.google.common.truth.Truth.assertAbout;
import static com.google.common.truth.Truth.assertThat;
import static com.google.gerrit.acceptance.server.change.ApprovalCopierIT.ApprovalDataSubject.assertThat;
import static com.google.gerrit.acceptance.server.change.ApprovalCopierIT.ApprovalDataSubject.assertThatList;
import static com.google.gerrit.acceptance.server.change.ApprovalCopierIT.ApprovalDataSubject.hasTestId;
import static com.google.gerrit.acceptance.testsuite.project.TestProjectUpdate.allowLabel;
import static com.google.gerrit.server.group.SystemGroupBackend.REGISTERED_USERS;
import static com.google.gerrit.server.project.testing.TestLabels.labelBuilder;
import static com.google.gerrit.server.project.testing.TestLabels.value;
import static com.google.gerrit.truth.ListSubject.elements;
import com.google.auto.value.AutoValue;
import com.google.common.collect.ImmutableSet;
import com.google.common.truth.Correspondence;
import com.google.common.truth.FailureMetadata;
import com.google.common.truth.StandardSubjectBuilder;
import com.google.common.truth.StringSubject;
import com.google.common.truth.Subject;
import com.google.common.truth.Truth8;
import com.google.gerrit.acceptance.AbstractDaemonTest;
import com.google.gerrit.acceptance.NoHttpd;
import com.google.gerrit.acceptance.PushOneCommit;
import com.google.gerrit.acceptance.TestAccount;
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.LabelId;
import com.google.gerrit.entities.LabelType;
import com.google.gerrit.entities.PatchSet;
import com.google.gerrit.entities.PatchSetApproval;
import com.google.gerrit.entities.RefNames;
import com.google.gerrit.extensions.api.changes.ReviewInput;
import com.google.gerrit.extensions.client.ChangeKind;
import com.google.gerrit.extensions.restapi.RestApiException;
import com.google.gerrit.server.approval.ApprovalCopier;
import com.google.gerrit.server.query.change.ChangeData;
import com.google.gerrit.truth.ListSubject;
import com.google.gerrit.truth.NullAwareCorrespondence;
import com.google.inject.Inject;
import java.io.IOException;
import java.util.Optional;
import java.util.Set;
import java.util.function.Predicate;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.revwalk.RevWalk;
import org.junit.Before;
import org.junit.Test;
/**
* Tests of the {@link ApprovalCopier} API.
*
* <p>This class doesn't verify the copy condition predicates, as they are already covered by {@code
* StickyApprovalsIT}.
*/
@NoHttpd
public class ApprovalCopierIT extends AbstractDaemonTest {
@Inject private ApprovalCopier approvalCopier;
@Inject private ProjectOperations projectOperations;
@Inject private RequestScopeOperations requestScopeOperations;
@Before
public void setup() throws Exception {
// Overwrite "Code-Review" label that is inherited from All-Projects.
try (ProjectConfigUpdate u = updateProject(project)) {
LabelType.Builder codeReview =
labelBuilder(
LabelId.CODE_REVIEW,
value(2, "Looks good to me, approved"),
value(1, "Looks good to me, but someone else must approve"),
value(0, "No score"),
value(-1, "I would prefer this is not submitted as is"),
value(-2, "This shall not be submitted"))
.setCopyCondition(
String.format(
"changekind:%s OR changekind:%s OR is:MIN",
ChangeKind.NO_CHANGE, ChangeKind.TRIVIAL_REBASE.name()));
u.getConfig().upsertLabelType(codeReview.build());
u.save();
}
// Add Verified label.
try (ProjectConfigUpdate u = updateProject(project)) {
LabelType.Builder verified =
labelBuilder(
LabelId.VERIFIED, value(1, "Passes"), value(0, "No score"), value(-1, "Failed"))
.setCopyCondition("is:MIN");
u.getConfig().upsertLabelType(verified.build());
u.save();
}
// Grant permissions to vote on the verified label.
projectOperations
.project(project)
.forUpdate()
.add(
allowLabel(LabelId.VERIFIED)
.ref(RefNames.REFS_HEADS + "*")
.group(REGISTERED_USERS)
.range(-1, 1))
.update();
}
@Test
public void forInitialPatchSet_noApprovals() throws Exception {
ChangeData changeData = createChange().getChange();
try (Repository repo = repoManager.openRepository(project);
RevWalk revWalk = new RevWalk(repo)) {
ApprovalCopier.Result approvalCopierResult =
approvalCopier.forPatchSet(
changeData.notes(), changeData.currentPatchSet(), revWalk, repo.getConfig());
assertThat(approvalCopierResult.copiedApprovals()).isEmpty();
assertThat(approvalCopierResult.outdatedApprovals()).isEmpty();
}
}
@Test
public void forInitialPatchSet_currentApprovals() throws Exception {
PushOneCommit.Result r = createChange();
// Add some current approvals.
vote(r.getChangeId(), admin, LabelId.CODE_REVIEW, 2);
vote(r.getChangeId(), admin, LabelId.VERIFIED, 1);
vote(r.getChangeId(), user, LabelId.CODE_REVIEW, -1);
vote(r.getChangeId(), user, LabelId.VERIFIED, -1);
ApprovalCopier.Result approvalCopierResult =
invokeApprovalCopierForCurrentPatchSet(
r.getChange().getId(), /* expectedCurrentPatchSetNum= */ 1);
assertThatList(approvalCopierResult.copiedApprovals()).isEmpty();
assertThatList(approvalCopierResult.outdatedApprovals()).isEmpty();
}
@Test
public void forPatchSet_noApprovals() throws Exception {
PushOneCommit.Result r = createChange();
amendChange(r.getChangeId(), "refs/for/master", admin, testRepo).assertOkStatus();
ApprovalCopier.Result approvalCopierResult =
invokeApprovalCopierForCurrentPatchSet(
r.getChange().getId(), /* expectedCurrentPatchSetNum= */ 2);
assertThatList(approvalCopierResult.copiedApprovals()).isEmpty();
assertThatList(approvalCopierResult.outdatedApprovals()).isEmpty();
}
@Test
public void forPatchSet_outdatedApprovals() throws Exception {
PushOneCommit.Result r = createChange();
PatchSet.Id patchSet1Id = r.getPatchSetId();
// Add some approvals that are not copied.
vote(r.getChangeId(), admin, LabelId.CODE_REVIEW, 2);
vote(r.getChangeId(), user, LabelId.VERIFIED, 1);
amendChange(r.getChangeId(), "refs/for/master", admin, testRepo).assertOkStatus();
ApprovalCopier.Result approvalCopierResult =
invokeApprovalCopierForCurrentPatchSet(
r.getChange().getId(), /* expectedCurrentPatchSetNum= */ 2);
assertThat(approvalCopierResult.copiedApprovals()).isEmpty();
assertThat(approvalCopierResult.outdatedApprovals())
.comparingElementsUsing(hasTestId())
.containsExactly(
PatchSetApprovalTestId.create(patchSet1Id, admin.id(), LabelId.CODE_REVIEW, 2),
PatchSetApprovalTestId.create(patchSet1Id, user.id(), LabelId.VERIFIED, 1));
ApprovalDataSubject codeReviewApprovalSubject =
assertThat(approvalCopierResult.outdatedApprovals(), LabelId.CODE_REVIEW, admin.id());
codeReviewApprovalSubject.hasPassingAtomsThat().isEmpty();
codeReviewApprovalSubject
.hasFailingAtomsThat()
.containsExactly("changekind:NO_CHANGE", "changekind:TRIVIAL_REBASE", "is:MIN");
ApprovalDataSubject verifiedApprovalSubject =
assertThat(approvalCopierResult.outdatedApprovals(), LabelId.VERIFIED, user.id());
verifiedApprovalSubject.hasPassingAtomsThat().isEmpty();
verifiedApprovalSubject.hasFailingAtomsThat().containsExactly("is:MIN");
}
@Test
public void forPatchSet_copiedApprovals() throws Exception {
PushOneCommit.Result r = createChange();
// Add some approvals that are copied.
vote(r.getChangeId(), admin, LabelId.CODE_REVIEW, -2);
vote(r.getChangeId(), user, LabelId.VERIFIED, -1);
r = amendChange(r.getChangeId(), "refs/for/master", admin, testRepo);
r.assertOkStatus();
PatchSet.Id patchSet2Id = r.getPatchSetId();
ApprovalCopier.Result approvalCopierResult =
invokeApprovalCopierForCurrentPatchSet(
r.getChange().getId(), /* expectedCurrentPatchSetNum= */ 2);
assertThatList(approvalCopierResult.copiedApprovals())
.comparingElementsUsing(hasTestId())
.containsExactly(
PatchSetApprovalTestId.create(patchSet2Id, admin.id(), LabelId.CODE_REVIEW, -2),
PatchSetApprovalTestId.create(patchSet2Id, user.id(), LabelId.VERIFIED, -1));
assertThatList(approvalCopierResult.outdatedApprovals()).isEmpty();
ApprovalDataSubject codeReviewApprovalSubject =
assertThat(approvalCopierResult.copiedApprovals(), LabelId.CODE_REVIEW, admin.id());
codeReviewApprovalSubject.hasPassingAtomsThat().containsExactly("is:MIN");
codeReviewApprovalSubject
.hasFailingAtomsThat()
.containsExactly("changekind:NO_CHANGE", "changekind:TRIVIAL_REBASE");
ApprovalDataSubject verifiedApprovalSubject =
assertThat(approvalCopierResult.copiedApprovals(), LabelId.VERIFIED, user.id());
verifiedApprovalSubject.hasPassingAtomsThat().containsExactly("is:MIN");
verifiedApprovalSubject.hasFailingAtomsThat().isEmpty();
}
@Test
public void forPatchSet_currentApprovals() throws Exception {
PushOneCommit.Result r = createChange();
amendChange(r.getChangeId(), "refs/for/master", admin, testRepo).assertOkStatus();
// Add some current approvals.
vote(r.getChangeId(), admin, LabelId.CODE_REVIEW, 2);
vote(r.getChangeId(), admin, LabelId.VERIFIED, 1);
vote(r.getChangeId(), user, LabelId.CODE_REVIEW, -1);
vote(r.getChangeId(), user, LabelId.VERIFIED, -1);
ApprovalCopier.Result approvalCopierResult =
invokeApprovalCopierForCurrentPatchSet(
r.getChange().getId(), /* expectedCurrentPatchSetNum= */ 2);
assertThatList(approvalCopierResult.copiedApprovals()).isEmpty();
assertThatList(approvalCopierResult.outdatedApprovals()).isEmpty();
}
@Test
public void forPatchSet_allKindOfApprovals() throws Exception {
PushOneCommit.Result r = createChange();
PatchSet.Id patchSet1Id = r.getPatchSetId();
// Add some approvals that are copied.
vote(r.getChangeId(), admin, LabelId.CODE_REVIEW, -2);
vote(r.getChangeId(), user, LabelId.VERIFIED, -1);
// Add some approvals that are not copied.
vote(r.getChangeId(), user, LabelId.CODE_REVIEW, 1);
vote(r.getChangeId(), admin, LabelId.VERIFIED, 1);
r = amendChange(r.getChangeId(), "refs/for/master", admin, testRepo);
r.assertOkStatus();
PatchSet.Id patchSet2Id = r.getPatchSetId();
// Add some current approvals.
vote(r.getChangeId(), user, LabelId.CODE_REVIEW, -1);
vote(r.getChangeId(), admin, LabelId.VERIFIED, -1);
ApprovalCopier.Result approvalCopierResult =
invokeApprovalCopierForCurrentPatchSet(
r.getChange().getId(), /* expectedCurrentPatchSetNum= */ 2);
assertThatList(approvalCopierResult.copiedApprovals())
.comparingElementsUsing(hasTestId())
.containsExactly(
PatchSetApprovalTestId.create(patchSet2Id, admin.id(), LabelId.CODE_REVIEW, -2),
PatchSetApprovalTestId.create(patchSet2Id, user.id(), LabelId.VERIFIED, -1));
assertThatList(approvalCopierResult.outdatedApprovals())
.comparingElementsUsing(hasTestId())
.containsExactly(
PatchSetApprovalTestId.create(patchSet1Id, user.id(), LabelId.CODE_REVIEW, 1),
PatchSetApprovalTestId.create(patchSet1Id, admin.id(), LabelId.VERIFIED, 1));
ApprovalDataSubject copiedCodeReviewApprovalSubject =
assertThat(approvalCopierResult.copiedApprovals(), LabelId.CODE_REVIEW, admin.id());
copiedCodeReviewApprovalSubject.hasPassingAtomsThat().containsExactly("is:MIN");
copiedCodeReviewApprovalSubject
.hasFailingAtomsThat()
.containsExactly("changekind:NO_CHANGE", "changekind:TRIVIAL_REBASE");
ApprovalDataSubject copiedVerifiedApprovalSubject =
assertThat(approvalCopierResult.copiedApprovals(), LabelId.VERIFIED, user.id());
copiedVerifiedApprovalSubject.hasPassingAtomsThat().containsExactly("is:MIN");
copiedVerifiedApprovalSubject.hasFailingAtomsThat().isEmpty();
ApprovalDataSubject outdatedCodeReviewApprovalSubject1 =
assertThat(approvalCopierResult.outdatedApprovals(), LabelId.CODE_REVIEW, user.id());
outdatedCodeReviewApprovalSubject1.hasPassingAtomsThat().isEmpty();
outdatedCodeReviewApprovalSubject1
.hasFailingAtomsThat()
.containsExactly("changekind:NO_CHANGE", "changekind:TRIVIAL_REBASE", "is:MIN");
ApprovalDataSubject outdatedVerifiedApprovalSubject1 =
assertThat(approvalCopierResult.outdatedApprovals(), LabelId.VERIFIED, admin.id());
outdatedVerifiedApprovalSubject1.hasPassingAtomsThat().isEmpty();
outdatedVerifiedApprovalSubject1.hasFailingAtomsThat().containsExactly("is:MIN");
}
@Test
public void forPatchSet_copiedApprovalOverriddenByCurrentApproval() throws Exception {
PushOneCommit.Result r = createChange();
// Add approval that is copied.
vote(r.getChangeId(), admin, LabelId.CODE_REVIEW, -2);
amendChange(r.getChangeId(), "refs/for/master", admin, testRepo).assertOkStatus();
// Override the copied approval.
vote(r.getChangeId(), admin, LabelId.CODE_REVIEW, 1);
ApprovalCopier.Result approvalCopierResult =
invokeApprovalCopierForCurrentPatchSet(
r.getChange().getId(), /* expectedCurrentPatchSetNum= */ 2);
assertThatList(approvalCopierResult.copiedApprovals()).isEmpty();
assertThatList(approvalCopierResult.outdatedApprovals()).isEmpty();
}
@Test
public void forPatchSet_approvalForNonExistingLabel() throws Exception {
PushOneCommit.Result r = createChange();
PatchSet.Id patchSet1Id = r.getPatchSetId();
// Add approval that could be copied.
vote(r.getChangeId(), admin, LabelId.CODE_REVIEW, -2);
// Delete the Code-Review label (override it with an empty label definition).
try (ProjectConfigUpdate u = updateProject(project)) {
u.getConfig().upsertLabelType(labelBuilder(LabelId.CODE_REVIEW).build());
u.save();
}
amendChange(r.getChangeId(), "refs/for/master", admin, testRepo).assertOkStatus();
ApprovalCopier.Result approvalCopierResult =
invokeApprovalCopierForCurrentPatchSet(
r.getChange().getId(), /* expectedCurrentPatchSetNum= */ 2);
assertThatList(approvalCopierResult.copiedApprovals()).isEmpty();
assertThatList(approvalCopierResult.outdatedApprovals())
.comparingElementsUsing(hasTestId())
.containsExactly(
PatchSetApprovalTestId.create(patchSet1Id, admin.id(), LabelId.CODE_REVIEW, -2));
ApprovalDataSubject codeReviewApprovalSubject1 =
assertThat(approvalCopierResult.outdatedApprovals(), LabelId.CODE_REVIEW, admin.id());
codeReviewApprovalSubject1.hasPassingAtomsThat().isEmpty();
codeReviewApprovalSubject1.hasFailingAtomsThat().isEmpty();
}
@Test
public void forPatchSet_copyableZeroApproval() throws Exception {
PushOneCommit.Result r = createChange();
// Override the inherited Code-Review label to make all votes copyable, including zero votes.
try (ProjectConfigUpdate u = updateProject(project)) {
LabelType.Builder codeReview =
labelBuilder(
LabelId.CODE_REVIEW,
value(2, "Looks good to me, approved"),
value(1, "Looks good to me, but someone else must approve"),
value(0, "No score"),
value(-1, "I would prefer this is not submitted as is"),
value(-2, "This shall not be submitted"))
.setCopyCondition("is:ANY");
u.getConfig().upsertLabelType(codeReview.build());
u.save();
}
// Create a zero approval that is copyable, by adding an approval and removing it again.
vote(r.getChangeId(), admin, LabelId.CODE_REVIEW, 2);
vote(r.getChangeId(), admin, LabelId.CODE_REVIEW, 0);
amendChange(r.getChangeId(), "refs/for/master", admin, testRepo).assertOkStatus();
ApprovalCopier.Result approvalCopierResult =
invokeApprovalCopierForCurrentPatchSet(
r.getChange().getId(), /* expectedCurrentPatchSetNum= */ 2);
assertThatList(approvalCopierResult.copiedApprovals()).isEmpty();
assertThatList(approvalCopierResult.outdatedApprovals()).isEmpty();
}
@Test
public void forPatchSet_nonCopyableZeroApproval() throws Exception {
PushOneCommit.Result r = createChange();
// Create a zero approval that is non-copyable, by adding an approval and removing it again.
vote(r.getChangeId(), admin, LabelId.CODE_REVIEW, 2);
vote(r.getChangeId(), admin, LabelId.CODE_REVIEW, 0);
amendChange(r.getChangeId(), "refs/for/master", admin, testRepo).assertOkStatus();
ApprovalCopier.Result approvalCopierResult =
invokeApprovalCopierForCurrentPatchSet(
r.getChange().getId(), /* expectedCurrentPatchSetNum= */ 2);
assertThatList(approvalCopierResult.copiedApprovals()).isEmpty();
assertThatList(approvalCopierResult.outdatedApprovals()).isEmpty();
}
@Test
public void copiedFlagSetOnCopiedApprovals() throws Exception {
PushOneCommit.Result r = createChange();
// Add approvals that are copied.
vote(r.getChangeId(), admin, LabelId.CODE_REVIEW, -2);
vote(r.getChangeId(), user, LabelId.VERIFIED, -1);
r = amendChange(r.getChangeId(), "refs/for/master", admin, testRepo);
r.assertOkStatus();
PatchSet.Id patchSet2Id = r.getPatchSetId();
// Override copied approval.
vote(r.getChangeId(), admin, LabelId.CODE_REVIEW, 1);
// Add new current approval.
vote(r.getChangeId(), admin, LabelId.VERIFIED, 1);
ApprovalCopier.Result approvalCopierResult =
invokeApprovalCopierForCurrentPatchSet(
r.getChange().getId(), /* expectedCurrentPatchSetNum= */ 2);
ImmutableSet<ApprovalCopier.Result.PatchSetApprovalData> copiedApprovals =
approvalCopierResult.copiedApprovals();
assertThatList(filter(copiedApprovals, approval -> approval.patchSetApproval().copied()))
.comparingElementsUsing(hasTestId())
.containsExactly(
PatchSetApprovalTestId.create(patchSet2Id, user.id(), LabelId.VERIFIED, -1));
assertThatList(filter(copiedApprovals, approval -> !approval.patchSetApproval().copied()))
.isEmpty();
}
private void vote(String changeId, TestAccount testAccount, String label, int value)
throws RestApiException {
requestScopeOperations.setApiUser(testAccount.id());
gApi.changes().id(changeId).current().review(new ReviewInput().label(label, value));
requestScopeOperations.setApiUser(admin.id());
}
private ImmutableSet<ApprovalCopier.Result.PatchSetApprovalData> filter(
Set<ApprovalCopier.Result.PatchSetApprovalData> approvals,
Predicate<ApprovalCopier.Result.PatchSetApprovalData> filter) {
return approvals.stream().filter(filter).collect(toImmutableSet());
}
private ApprovalCopier.Result invokeApprovalCopierForCurrentPatchSet(
Change.Id changeId, int expectedCurrentPatchSetNum) throws IOException {
ChangeData changeData = changeDataFactory.create(project, changeId);
assertThat(changeData.currentPatchSet().id().get()).isEqualTo(expectedCurrentPatchSetNum);
try (Repository repo = repoManager.openRepository(project);
RevWalk revWalk = new RevWalk(repo)) {
return approvalCopier.forPatchSet(
changeData.notes(), changeData.currentPatchSet(), revWalk, repo.getConfig());
}
}
public static class ApprovalDataSubject extends Subject {
public static Correspondence<ApprovalCopier.Result.PatchSetApprovalData, PatchSetApprovalTestId>
hasTestId() {
return NullAwareCorrespondence.transforming(
approvalData -> PatchSetApprovalTestId.create(approvalData.patchSetApproval()),
"has test ID");
}
public static ApprovalDataSubject assertThat(
ApprovalCopier.Result.PatchSetApprovalData approvalData) {
return assertAbout(approvalDatas()).that(approvalData);
}
public static ApprovalDataSubject assertThat(
ImmutableSet<ApprovalCopier.Result.PatchSetApprovalData> approvalDatas,
String labelId,
Account.Id accountId) {
Optional<ApprovalCopier.Result.PatchSetApprovalData> approvalDataForLabelAndAccount =
approvalDatas.stream()
.filter(
approvalData ->
approvalData.patchSetApproval().label().equals(labelId)
&& approvalData.patchSetApproval().accountId().equals(accountId))
.findAny();
Truth8.assertThat(approvalDataForLabelAndAccount).isPresent();
return assertAbout(approvalDatas()).that(approvalDataForLabelAndAccount.get());
}
public static ListSubject<ApprovalDataSubject, ApprovalCopier.Result.PatchSetApprovalData>
assertThatList(ImmutableSet<ApprovalCopier.Result.PatchSetApprovalData> approvalDatas) {
return ListSubject.assertThat(approvalDatas.asList(), approvalDatas());
}
private static Factory<ApprovalDataSubject, ApprovalCopier.Result.PatchSetApprovalData>
approvalDatas() {
return ApprovalDataSubject::new;
}
private final ApprovalCopier.Result.PatchSetApprovalData approvalData;
private ApprovalDataSubject(
FailureMetadata metadata, ApprovalCopier.Result.PatchSetApprovalData approvalData) {
super(metadata, approvalData);
this.approvalData = approvalData;
}
public ListSubject<StringSubject, String> hasPassingAtomsThat() {
return check("passingAtoms()")
.about(elements())
.that(approvalData().passingAtoms().asList(), StandardSubjectBuilder::that);
}
public ListSubject<StringSubject, String> hasFailingAtomsThat() {
return check("failingAtoms()")
.about(elements())
.that(approvalData().failingAtoms().asList(), StandardSubjectBuilder::that);
}
private ApprovalCopier.Result.PatchSetApprovalData approvalData() {
isNotNull();
return approvalData;
}
}
public static class PatchSetApprovalSubject extends Subject {
public static PatchSetApprovalSubject assertThat(PatchSetApproval patchSetApproval) {
return assertAbout(patchSetApprovals()).that(patchSetApproval);
}
private static Factory<PatchSetApprovalSubject, PatchSetApproval> patchSetApprovals() {
return PatchSetApprovalSubject::new;
}
private PatchSetApprovalSubject(FailureMetadata metadata, PatchSetApproval patchSetApproval) {
super(metadata, patchSetApproval);
}
}
/**
* AutoValue class that contains all properties of a PatchSetApproval that are relevant to do
* assertions in tests (patch set ID, account ID, label name, voting value).
*/
@AutoValue
public abstract static class PatchSetApprovalTestId {
public abstract PatchSet.Id patchSetId();
public abstract Account.Id accountId();
public abstract LabelId labelId();
public abstract short value();
public static PatchSetApprovalTestId create(PatchSetApproval patchSetApproval) {
return new AutoValue_ApprovalCopierIT_PatchSetApprovalTestId(
patchSetApproval.patchSetId(),
patchSetApproval.accountId(),
patchSetApproval.labelId(),
patchSetApproval.value());
}
public static PatchSetApprovalTestId create(
PatchSet.Id patchSetId, Account.Id accountId, String labelId, int value) {
return new AutoValue_ApprovalCopierIT_PatchSetApprovalTestId(
patchSetId, accountId, LabelId.create(labelId), (short) value);
}
}
}