Merge "Read SRs from the revision note of the last PS that has stored SRs"
diff --git a/java/com/google/gerrit/acceptance/AbstractDaemonTest.java b/java/com/google/gerrit/acceptance/AbstractDaemonTest.java
index b5835c9..eb77677 100644
--- a/java/com/google/gerrit/acceptance/AbstractDaemonTest.java
+++ b/java/com/google/gerrit/acceptance/AbstractDaemonTest.java
@@ -1646,6 +1646,13 @@
}
}
+ protected void clearSubmitRequirements(Project.NameKey project) throws Exception {
+ try (ProjectConfigUpdate u = updateProject(project)) {
+ u.getConfig().clearSubmitRequirements();
+ u.save();
+ }
+ }
+
protected void configLabel(String label, LabelFunction func) throws Exception {
configLabel(label, func, ImmutableList.of());
}
diff --git a/java/com/google/gerrit/server/notedb/ChangeNotes.java b/java/com/google/gerrit/server/notedb/ChangeNotes.java
index 3dae2b8..0c6f518 100644
--- a/java/com/google/gerrit/server/notedb/ChangeNotes.java
+++ b/java/com/google/gerrit/server/notedb/ChangeNotes.java
@@ -487,11 +487,19 @@
/**
* Returns the evaluated submit requirements for the change. We only intend to store submit
- * requirements in NoteDb for closed changes, hence the result will be an empty list for active
- * changes, or a list of submit requirements results otherwise. For closed changes, the results
- * represent the state of evaluating submit requirements for this change when it was merged.
+ * requirements in NoteDb for closed changes. For closed changes, the results represent the state
+ * of evaluating submit requirements for this change when it was merged or abandoned.
+ *
+ * @throws UnsupportedOperationException if submit requirements are requested for an open change.
*/
public ImmutableList<SubmitRequirementResult> getSubmitRequirementsResult() {
+ if (state.columns().status().isOpen()) {
+ throw new UnsupportedOperationException(
+ String.format(
+ "Cannot request stored submit requirements"
+ + " for an open change: project = %s, change ID = %d",
+ getProjectName(), state.changeId().get()));
+ }
return state.submitRequirementsResult();
}
diff --git a/java/com/google/gerrit/server/notedb/ChangeNotesParser.java b/java/com/google/gerrit/server/notedb/ChangeNotesParser.java
index ec98f6ea..463c141 100644
--- a/java/com/google/gerrit/server/notedb/ChangeNotesParser.java
+++ b/java/com/google/gerrit/server/notedb/ChangeNotesParser.java
@@ -863,8 +863,28 @@
for (HumanComment c : e.getValue().getEntities()) {
humanComments.put(e.getKey(), c);
}
- for (SubmitRequirementResult sr : e.getValue().getSubmitRequirementsResult()) {
- submitRequirementResults.add(sr);
+ }
+
+ // Lookup submit requirement results from the revision notes of the last PS that has stored
+ // submit requirements. This is important for cases where the change was abandoned/un-abandoned
+ // multiple times. With each abandon, we store submit requirement results in NoteDb, so we can
+ // end up having stored SRs in many revision notes. We should only return SRs from the last
+ // PS of them.
+ for (PatchSet.Builder ps :
+ patchSets.values().stream()
+ .sorted(comparingInt((PatchSet.Builder p) -> p.id().get()).reversed())
+ .collect(Collectors.toList())) {
+ Optional<ObjectId> maybePsCommitId = ps.commitId();
+ if (!maybePsCommitId.isPresent()) {
+ continue;
+ }
+ ObjectId psCommitId = maybePsCommitId.get();
+ if (rns.containsKey(psCommitId)
+ && rns.get(psCommitId).getSubmitRequirementsResult() != null) {
+ rns.get(psCommitId)
+ .getSubmitRequirementsResult()
+ .forEach(sr -> submitRequirementResults.add(sr));
+ break;
}
}
diff --git a/java/com/google/gerrit/server/notedb/ChangeRevisionNote.java b/java/com/google/gerrit/server/notedb/ChangeRevisionNote.java
index cb3a5ac..6d49fc8 100644
--- a/java/com/google/gerrit/server/notedb/ChangeRevisionNote.java
+++ b/java/com/google/gerrit/server/notedb/ChangeRevisionNote.java
@@ -17,6 +17,7 @@
import static java.nio.charset.StandardCharsets.UTF_8;
import com.google.common.collect.ImmutableList;
+import com.google.gerrit.common.Nullable;
import com.google.gerrit.entities.Comment;
import com.google.gerrit.entities.HumanComment;
import com.google.gerrit.entities.SubmitRequirementResult;
@@ -37,7 +38,12 @@
private final Comment.Status status;
private String pushCert;
- private ImmutableList<SubmitRequirementResult> submitRequirementsResult;
+ /**
+ * Submit requirement results stored in this revision note. If null, then no SRs were stored in
+ * the revision note . Otherwise, there were stored SRs in this revision note. The list could be
+ * empty, meaning that no SRs were configured for the project.
+ */
+ @Nullable private ImmutableList<SubmitRequirementResult> submitRequirementsResult;
ChangeRevisionNote(
ChangeNoteJson noteJson, ObjectReader reader, ObjectId noteId, Comment.Status status) {
@@ -46,6 +52,12 @@
this.status = status;
}
+ /**
+ * Returns null if no submit requirements were stored in the revision note. Otherwise, this method
+ * returns a list of submit requirements, which can probably be empty if there were no SRs
+ * configured for the project at the time when the SRs were stored.
+ */
+ @Nullable
public ImmutableList<SubmitRequirementResult> getSubmitRequirementsResult() {
checkParsed();
return submitRequirementsResult;
@@ -70,7 +82,7 @@
}
this.submitRequirementsResult =
data.submitRequirementResults == null
- ? ImmutableList.of()
+ ? null
: ImmutableList.copyOf(data.submitRequirementResults);
return data.comments;
}
diff --git a/java/com/google/gerrit/server/notedb/ChangeUpdate.java b/java/com/google/gerrit/server/notedb/ChangeUpdate.java
index 961a5ee..4894140 100644
--- a/java/com/google/gerrit/server/notedb/ChangeUpdate.java
+++ b/java/com/google/gerrit/server/notedb/ChangeUpdate.java
@@ -52,6 +52,7 @@
import com.google.common.base.Strings;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Iterables;
import com.google.common.collect.Table;
import com.google.common.collect.Table.Cell;
import com.google.common.collect.TreeBasedTable;
@@ -138,7 +139,6 @@
private final Map<Account.Id, ReviewerStateInternal> reviewers = new LinkedHashMap<>();
private final Map<Address, ReviewerStateInternal> reviewersByEmail = new LinkedHashMap<>();
private final List<HumanComment> comments = new ArrayList<>();
- private final List<SubmitRequirementResult> submitRequirementResults = new ArrayList<>();
private String commitSubject;
private String subject;
@@ -172,6 +172,7 @@
private RobotCommentUpdate robotCommentUpdate;
private DeleteCommentRewriter deleteCommentRewriter;
private DeleteChangeMessageRewriter deleteChangeMessageRewriter;
+ private List<SubmitRequirementResult> submitRequirementResults;
@AssistedInject
private ChangeUpdate(
@@ -326,6 +327,9 @@
}
public void putSubmitRequirementResults(Collection<SubmitRequirementResult> rs) {
+ if (submitRequirementResults == null) {
+ submitRequirementResults = new ArrayList<>();
+ }
submitRequirementResults.addAll(rs);
}
@@ -515,7 +519,7 @@
/** Returns the tree id for the updated tree */
private ObjectId storeRevisionNotes(RevWalk rw, ObjectInserter inserter, ObjectId curr)
throws ConfigInvalidException, IOException {
- if (submitRequirementResults.isEmpty() && comments.isEmpty() && pushCert == null) {
+ if (submitRequirementResults == null && comments.isEmpty() && pushCert == null) {
return null;
}
RevisionNoteMap<ChangeRevisionNote> rnm = getRevisionNoteMap(rw, curr);
@@ -525,8 +529,16 @@
c.tag = tag;
cache.get(c.getCommitId()).putComment(c);
}
- for (SubmitRequirementResult sr : submitRequirementResults) {
- cache.get(sr.patchSetCommitId()).putSubmitRequirementResult(sr);
+ if (submitRequirementResults != null) {
+ if (submitRequirementResults.isEmpty()) {
+ ObjectId latestPsCommitId =
+ Iterables.getLast(getNotes().getPatchSets().values()).commitId();
+ cache.get(latestPsCommitId).createEmptySubmitRequirementResults();
+ } else {
+ for (SubmitRequirementResult sr : submitRequirementResults) {
+ cache.get(sr.patchSetCommitId()).putSubmitRequirementResult(sr);
+ }
+ }
}
if (pushCert != null) {
checkState(commit != null);
diff --git a/java/com/google/gerrit/server/notedb/RevisionNoteBuilder.java b/java/com/google/gerrit/server/notedb/RevisionNoteBuilder.java
index 7998476..ac9fa48 100644
--- a/java/com/google/gerrit/server/notedb/RevisionNoteBuilder.java
+++ b/java/com/google/gerrit/server/notedb/RevisionNoteBuilder.java
@@ -21,6 +21,7 @@
import com.google.common.collect.ListMultimap;
import com.google.common.collect.Maps;
import com.google.common.collect.MultimapBuilder;
+import com.google.gerrit.common.Nullable;
import com.google.gerrit.entities.Comment;
import com.google.gerrit.entities.SubmitRequirementResult;
import java.io.ByteArrayOutputStream;
@@ -73,7 +74,13 @@
final Map<Comment.Key, Comment> put;
private final Set<Comment.Key> delete;
- private List<SubmitRequirementResult> submitRequirementResults;
+ /**
+ * Submit requirement results to be stored in the revision note. If this field is null, we don't
+ * store results in the revision note. Otherwise, we store a "submit requirements" section in the
+ * revision note even if it's empty.
+ */
+ @Nullable private List<SubmitRequirementResult> submitRequirementResults;
+
private String pushCert;
private RevisionNoteBuilder(RevisionNote<? extends Comment> base) {
@@ -90,7 +97,6 @@
put = new HashMap<>();
pushCert = null;
}
- submitRequirementResults = new ArrayList<>();
delete = new HashSet<>();
}
@@ -109,7 +115,18 @@
put.put(comment.key, comment);
}
+ /**
+ * Call this method to designate that we should store submit requirement results in the revision
+ * note. Even if no results are added, an empty submit requirements section will be added.
+ */
+ void createEmptySubmitRequirementResults() {
+ submitRequirementResults = new ArrayList<>();
+ }
+
void putSubmitRequirementResult(SubmitRequirementResult result) {
+ if (submitRequirementResults == null) {
+ submitRequirementResults = new ArrayList<>();
+ }
submitRequirementResults.add(result);
}
@@ -140,19 +157,19 @@
private void buildNoteJson(ChangeNoteJson noteUtil, OutputStream out) throws IOException {
ListMultimap<Integer, Comment> comments = buildCommentMap();
- if (submitRequirementResults.isEmpty() && comments.isEmpty() && pushCert == null) {
+ if (submitRequirementResults == null && comments.isEmpty() && pushCert == null) {
return;
}
RevisionNoteData data = new RevisionNoteData();
data.comments = COMMENT_ORDER.sortedCopy(comments.values());
data.pushCert = pushCert;
- if (!submitRequirementResults.isEmpty()) {
- data.submitRequirementResults =
- submitRequirementResults.stream()
- .sorted(SUBMIT_REQUIREMENT_RESULT_COMPARATOR)
- .collect(Collectors.toList());
- }
+ data.submitRequirementResults =
+ submitRequirementResults == null
+ ? null
+ : submitRequirementResults.stream()
+ .sorted(SUBMIT_REQUIREMENT_RESULT_COMPARATOR)
+ .collect(Collectors.toList());
try (OutputStreamWriter osw = new OutputStreamWriter(out, UTF_8)) {
noteUtil.getGson().toJson(data, osw);
diff --git a/java/com/google/gerrit/server/project/ProjectConfig.java b/java/com/google/gerrit/server/project/ProjectConfig.java
index b620193..03886a9 100644
--- a/java/com/google/gerrit/server/project/ProjectConfig.java
+++ b/java/com/google/gerrit/server/project/ProjectConfig.java
@@ -23,6 +23,7 @@
import static java.util.Objects.requireNonNull;
import static java.util.stream.Collectors.toList;
+import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.CharMatcher;
import com.google.common.base.Joiner;
import com.google.common.base.Splitter;
@@ -532,6 +533,11 @@
submitRequirementSections.put(requirement.name(), requirement);
}
+ @VisibleForTesting
+ public void clearSubmitRequirements() {
+ submitRequirementSections = new LinkedHashMap<>();
+ }
+
/** Adds or replaces the given {@link LabelType} in this config. */
public void upsertLabelType(LabelType labelType) {
labelSections.put(labelType.getName(), labelType);
diff --git a/javatests/com/google/gerrit/acceptance/api/change/ChangeIT.java b/javatests/com/google/gerrit/acceptance/api/change/ChangeIT.java
index 54e1897..38e465f 100644
--- a/javatests/com/google/gerrit/acceptance/api/change/ChangeIT.java
+++ b/javatests/com/google/gerrit/acceptance/api/change/ChangeIT.java
@@ -5137,6 +5137,277 @@
value =
ExperimentFeaturesConstants
.GERRIT_BACKEND_REQUEST_FEATURE_STORE_SUBMIT_REQUIREMENTS_ON_MERGE)
+ public void submitRequirement_loadedFromTheLatestRevisionNoteForClosedChanges() throws Exception {
+ for (SubmitType submitType : SubmitType.values()) {
+ Project.NameKey project = createProjectForPush(submitType);
+ TestRepository<InMemoryRepository> repo = cloneProject(project);
+ configSubmitRequirement(
+ project,
+ SubmitRequirement.builder()
+ .setName("Code-Review")
+ .setSubmittabilityExpression(
+ SubmitRequirementExpression.create("label:Code-Review=+2"))
+ .setAllowOverrideInChildProjects(false)
+ .build());
+
+ PushOneCommit.Result r =
+ createChange(repo, "master", "Add a file", "foo", "content", "topic");
+ String changeId = r.getChangeId();
+
+ // Abandon change. Submit requirements get stored in the revision note of patch-set 1.
+ gApi.changes().id(changeId).abandon();
+ ChangeInfo change = gApi.changes().id(changeId).get();
+ assertThat(change.submitRequirements).hasSize(1);
+ assertSubmitRequirementStatus(
+ change.submitRequirements, "Code-Review", Status.UNSATISFIED, /* isLegacy= */ false);
+
+ // Restore the change.
+ gApi.changes().id(changeId).restore();
+ change = gApi.changes().id(changeId).get();
+ assertThat(change.submitRequirements).hasSize(1);
+ assertSubmitRequirementStatus(
+ change.submitRequirements, "Code-Review", Status.UNSATISFIED, /* isLegacy= */ false);
+
+ // Upload a second patch-set, fulfill the CR submit requirement.
+ amendChange(changeId, "refs/for/master", user, repo);
+ change = gApi.changes().id(changeId).get();
+ assertThat(change.revisions).hasSize(2);
+ voteLabel(changeId, "Code-Review", 2);
+ change = gApi.changes().id(changeId).get();
+ assertThat(change.submitRequirements).hasSize(1);
+ assertSubmitRequirementStatus(
+ change.submitRequirements, "Code-Review", Status.SATISFIED, /* isLegacy= */ false);
+
+ // Abandon the change.
+ gApi.changes().id(changeId).abandon();
+ change = gApi.changes().id(changeId).get();
+ assertThat(change.submitRequirements).hasSize(1);
+ assertSubmitRequirementStatus(
+ change.submitRequirements, "Code-Review", Status.SATISFIED, /* isLegacy= */ false);
+ }
+ }
+
+ @Test
+ @GerritConfig(
+ name = "experiments.enabled",
+ value =
+ ExperimentFeaturesConstants
+ .GERRIT_BACKEND_REQUEST_FEATURE_STORE_SUBMIT_REQUIREMENTS_ON_MERGE)
+ public void submitRequirement_abandonRestoreUpdateMerge() throws Exception {
+ for (SubmitType submitType : SubmitType.values()) {
+ Project.NameKey project = createProjectForPush(submitType);
+ TestRepository<InMemoryRepository> repo = cloneProject(project);
+ configSubmitRequirement(
+ project,
+ SubmitRequirement.builder()
+ .setName("Code-Review")
+ .setSubmittabilityExpression(
+ SubmitRequirementExpression.create("label:Code-Review=+2"))
+ .setAllowOverrideInChildProjects(false)
+ .build());
+
+ PushOneCommit.Result r =
+ createChange(repo, "master", "Add a file", "foo", "content", "topic");
+ String changeId = r.getChangeId();
+
+ // Abandon change. Submit requirements get stored in the revision note of patch-set 1.
+ gApi.changes().id(changeId).abandon();
+ ChangeInfo change = gApi.changes().id(changeId).get();
+ assertThat(change.submitRequirements).hasSize(1);
+ assertSubmitRequirementStatus(
+ change.submitRequirements, "Code-Review", Status.UNSATISFIED, /* isLegacy= */ false);
+
+ // Restore the change.
+ gApi.changes().id(changeId).restore();
+ change = gApi.changes().id(changeId).get();
+ assertThat(change.submitRequirements).hasSize(1);
+ assertSubmitRequirementStatus(
+ change.submitRequirements, "Code-Review", Status.UNSATISFIED, /* isLegacy= */ false);
+
+ // Update the change.
+ amendChange(changeId, "refs/for/master", user, repo);
+ change = gApi.changes().id(changeId).get();
+ assertThat(change.revisions).hasSize(2);
+ voteLabel(changeId, "Code-Review", 2);
+ change = gApi.changes().id(changeId).get();
+ assertThat(change.submitRequirements).hasSize(1);
+ assertSubmitRequirementStatus(
+ change.submitRequirements, "Code-Review", Status.SATISFIED, /* isLegacy= */ false);
+
+ // Merge the change.
+ gApi.changes().id(changeId).current().submit();
+ change = gApi.changes().id(changeId).get();
+ assertThat(change.submitRequirements).hasSize(1);
+ assertSubmitRequirementStatus(
+ change.submitRequirements, "Code-Review", Status.SATISFIED, /* isLegacy= */ false);
+ }
+ }
+
+ @Test
+ @GerritConfig(
+ name = "experiments.enabled",
+ value =
+ ExperimentFeaturesConstants
+ .GERRIT_BACKEND_REQUEST_FEATURE_STORE_SUBMIT_REQUIREMENTS_ON_MERGE)
+ public void submitRequirement_returnsEmpty_ForAbandonedChangeWithPreviouslyStoredSRs()
+ throws Exception {
+ for (SubmitType submitType : SubmitType.values()) {
+ Project.NameKey project = createProjectForPush(submitType);
+ TestRepository<InMemoryRepository> repo = cloneProject(project);
+ configSubmitRequirement(
+ project,
+ SubmitRequirement.builder()
+ .setName("Code-Review")
+ .setSubmittabilityExpression(
+ SubmitRequirementExpression.create("label:Code-Review=+2"))
+ .setAllowOverrideInChildProjects(false)
+ .build());
+
+ PushOneCommit.Result r =
+ createChange(repo, "master", "Add a file", "foo", "content", "topic");
+ String changeId = r.getChangeId();
+
+ // Abandon change. Submit requirements get stored in the revision note of patch-set 1.
+ gApi.changes().id(changeId).abandon();
+ ChangeInfo change = gApi.changes().id(changeId).get();
+ assertThat(change.submitRequirements).hasSize(1);
+ assertSubmitRequirementStatus(
+ change.submitRequirements, "Code-Review", Status.UNSATISFIED, /* isLegacy= */ false);
+
+ // Clear SRs for the project and update code-review label to be non-blocking.
+ clearSubmitRequirements(project);
+ LabelType cr =
+ TestLabels.codeReview().toBuilder().setFunction(LabelFunction.NO_BLOCK).build();
+ try (ProjectConfigUpdate u = updateProject(project)) {
+ u.getConfig().upsertLabelType(cr);
+ u.save();
+ }
+
+ // Restore the change. No SRs apply.
+ gApi.changes().id(changeId).restore();
+ change = gApi.changes().id(changeId).get();
+ assertThat(change.submitRequirements).isEmpty();
+
+ // Abandon the change. Still, no SRs apply.
+ gApi.changes().id(changeId).abandon();
+ change = gApi.changes().id(changeId).get();
+ assertThat(change.submitRequirements).isEmpty();
+ }
+ }
+
+ @Test
+ @GerritConfig(
+ name = "experiments.enabled",
+ value =
+ ExperimentFeaturesConstants
+ .GERRIT_BACKEND_REQUEST_FEATURE_STORE_SUBMIT_REQUIREMENTS_ON_MERGE)
+ public void submitRequirement_returnsEmpty_ForMergedChangeWithPreviouslyStoredSRs()
+ throws Exception {
+ for (SubmitType submitType : SubmitType.values()) {
+ Project.NameKey project = createProjectForPush(submitType);
+ TestRepository<InMemoryRepository> repo = cloneProject(project);
+ configSubmitRequirement(
+ project,
+ SubmitRequirement.builder()
+ .setName("Code-Review")
+ .setSubmittabilityExpression(
+ SubmitRequirementExpression.create("label:Code-Review=+2"))
+ .setAllowOverrideInChildProjects(false)
+ .build());
+
+ PushOneCommit.Result r =
+ createChange(repo, "master", "Add a file", "foo", "content", "topic");
+ String changeId = r.getChangeId();
+
+ // Abandon change. Submit requirements get stored in the revision note of patch-set 1.
+ gApi.changes().id(changeId).abandon();
+ ChangeInfo change = gApi.changes().id(changeId).get();
+ assertThat(change.submitRequirements).hasSize(1);
+ assertSubmitRequirementStatus(
+ change.submitRequirements, "Code-Review", Status.UNSATISFIED, /* isLegacy= */ false);
+
+ // Clear SRs for the project and update code-review label to be non-blocking.
+ clearSubmitRequirements(project);
+ LabelType cr =
+ TestLabels.codeReview().toBuilder().setFunction(LabelFunction.NO_BLOCK).build();
+ try (ProjectConfigUpdate u = updateProject(project)) {
+ u.getConfig().upsertLabelType(cr);
+ u.save();
+ }
+
+ // Restore the change. No SRs apply.
+ gApi.changes().id(changeId).restore();
+ change = gApi.changes().id(changeId).get();
+ assertThat(change.submitRequirements).isEmpty();
+
+ // Merge the change. Still, no SRs apply.
+ gApi.changes().id(changeId).current().submit();
+ change = gApi.changes().id(changeId).get();
+ assertThat(change.submitRequirements).isEmpty();
+ }
+ }
+
+ @Test
+ @GerritConfig(
+ name = "experiments.enabled",
+ value =
+ ExperimentFeaturesConstants
+ .GERRIT_BACKEND_REQUEST_FEATURE_STORE_SUBMIT_REQUIREMENTS_ON_MERGE)
+ public void submitRequirement_withMultipleAbandonAndRestore() throws Exception {
+ for (SubmitType submitType : SubmitType.values()) {
+ Project.NameKey project = createProjectForPush(submitType);
+ TestRepository<InMemoryRepository> repo = cloneProject(project);
+ configSubmitRequirement(
+ project,
+ SubmitRequirement.builder()
+ .setName("Code-Review")
+ .setSubmittabilityExpression(
+ SubmitRequirementExpression.create("label:Code-Review=+2"))
+ .setAllowOverrideInChildProjects(false)
+ .build());
+
+ PushOneCommit.Result r =
+ createChange(repo, "master", "Add a file", "foo", "content", "topic");
+ String changeId = r.getChangeId();
+
+ // Abandon change. Submit requirements get stored in the revision note of patch-set 1.
+ gApi.changes().id(changeId).abandon();
+ ChangeInfo change = gApi.changes().id(changeId).get();
+ assertThat(change.submitRequirements).hasSize(1);
+ assertSubmitRequirementStatus(
+ change.submitRequirements, "Code-Review", Status.UNSATISFIED, /* isLegacy= */ false);
+
+ // Restore the change.
+ gApi.changes().id(changeId).restore();
+ change = gApi.changes().id(changeId).get();
+ assertThat(change.submitRequirements).hasSize(1);
+ assertSubmitRequirementStatus(
+ change.submitRequirements, "Code-Review", Status.UNSATISFIED, /* isLegacy= */ false);
+
+ // Abandon the change again.
+ gApi.changes().id(changeId).abandon();
+ change = gApi.changes().id(changeId).get();
+ assertThat(change.submitRequirements).hasSize(1);
+ assertSubmitRequirementStatus(
+ change.submitRequirements, "Code-Review", Status.UNSATISFIED, /* isLegacy= */ false);
+
+ // Restore, vote CR=+2, and abandon again. Make sure the requirement is now satisfied.
+ gApi.changes().id(changeId).restore();
+ voteLabel(changeId, "Code-Review", 2);
+ gApi.changes().id(changeId).abandon();
+ change = gApi.changes().id(changeId).get();
+ assertThat(change.submitRequirements).hasSize(1);
+ assertSubmitRequirementStatus(
+ change.submitRequirements, "Code-Review", Status.SATISFIED, /* isLegacy= */ false);
+ }
+ }
+
+ @Test
+ @GerritConfig(
+ name = "experiments.enabled",
+ value =
+ ExperimentFeaturesConstants
+ .GERRIT_BACKEND_REQUEST_FEATURE_STORE_SUBMIT_REQUIREMENTS_ON_MERGE)
public void submitRequirement_retrievedFromNoteDbForAbandonedChanges() throws Exception {
for (SubmitType submitType : SubmitType.values()) {
Project.NameKey project = createProjectForPush(submitType);