From d032872af8d1e8d9b63e50dfe6359360a53c9f3c Mon Sep 17 00:00:00 2001 From: Luke Alonso Date: Tue, 29 Dec 2020 17:25:46 -0800 Subject: Fix 'is:submittable' query on multiple submit records When a project has multiple submit rules, which produce multiple submit records, the 'is:submittable' query stops working as the documentation indicates it should. Rather than returning changes that are ready to be submitted, it returns any change where at least one submit record is OK, despite the overall change not being submittable. For example, with the code-owners plugin, which uses a java-based submit rule, 'is:submittable' will return changes that are passing owners checks, but might have CodeReview:-2 or Verified:-1. For projects with a single submit rule, the behavior is exactly the same as before, since we simply check that *any* of the submit records is OK, exactly as before, AND that *none* of them are NOT_READY or RULE_ERROR. Bug: Issue 13884 Change-Id: I4878ce13c6673852916d6891253d5e62b46f3db5 --- .../server/query/change/ChangeQueryBuilder.java | 10 +- .../api/change/ChangeSubmitRequirementIT.java | 104 ++++++++++++++++++++- 2 files changed, 108 insertions(+), 6 deletions(-) diff --git a/java/com/google/gerrit/server/query/change/ChangeQueryBuilder.java b/java/com/google/gerrit/server/query/change/ChangeQueryBuilder.java index df729cb63c..6f278ab712 100644 --- a/java/com/google/gerrit/server/query/change/ChangeQueryBuilder.java +++ b/java/com/google/gerrit/server/query/change/ChangeQueryBuilder.java @@ -570,7 +570,15 @@ public class ChangeQueryBuilder extends QueryBuilder result = queryIsSubmittable(); + assertThat(result).hasSize(1); + assertThat(result.get(0).changeId).isEqualTo(change.info().changeId); + } + + @Test + public void submittableQueryRuleNoRecord() throws Exception { + ChangeApi change = newChangeApi(); + + // Satisfy the default rule. + approveChange(change); + + // Our custom rule isn't providing any submit records. + rule.status(Optional.empty()); + change.index(); + + // is:submittable should return the change, since it was approved and the custom rule is not + // blocking it. + List result = queryIsSubmittable(); + assertThat(result).hasSize(1); + assertThat(result.get(0).changeId).isEqualTo(change.info().changeId); + } + + private List queryIsSubmittable() throws Exception { + return gApi.changes().query("is:submittable project:" + project.get()).get(); + } + + private ChangeApi newChangeApi() throws Exception { + return gApi.changes().id(createChange().getChangeId()); + } + + private void approveChange(ChangeApi changeApi) throws Exception { + changeApi.current().review(ReviewInput.approve()); + } + + private void rejectChange(ChangeApi changeApi) throws Exception { + changeApi.current().review(ReviewInput.reject()); + } + @Singleton private static class CustomSubmitRule implements SubmitRule { - private final AtomicBoolean block = new AtomicBoolean(true); + private Optional recordStatus = Optional.empty(); public void block(boolean block) { - this.block.set(block); + this.status(block ? Optional.of(SubmitRecord.Status.NOT_READY) : Optional.empty()); + } + + public void status(Optional status) { + this.recordStatus = status; } @Override public Optional evaluate(ChangeData changeData) { - if (block.get()) { + if (this.recordStatus.isPresent()) { SubmitRecord record = new SubmitRecord(); record.labels = new ArrayList<>(); - record.status = SubmitRecord.Status.NOT_READY; + record.status = this.recordStatus.get(); record.requirements = ImmutableList.of(req); return Optional.of(record); } -- cgit v1.2.3