diff options
Diffstat (limited to 'javatests/com/google/gerrit/acceptance/server/rules/PrologRuleEvaluatorIT.java')
-rw-r--r-- | javatests/com/google/gerrit/acceptance/server/rules/PrologRuleEvaluatorIT.java | 160 |
1 files changed, 160 insertions, 0 deletions
diff --git a/javatests/com/google/gerrit/acceptance/server/rules/PrologRuleEvaluatorIT.java b/javatests/com/google/gerrit/acceptance/server/rules/PrologRuleEvaluatorIT.java new file mode 100644 index 0000000000..8fc32b400f --- /dev/null +++ b/javatests/com/google/gerrit/acceptance/server/rules/PrologRuleEvaluatorIT.java @@ -0,0 +1,160 @@ +// Copyright (C) 2018 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.rules; + +import static com.google.common.truth.Truth.assertThat; + +import com.google.common.collect.ImmutableList; +import com.google.gerrit.acceptance.AbstractDaemonTest; +import com.google.gerrit.acceptance.TestAccount; +import com.google.gerrit.common.data.SubmitRecord; +import com.google.gerrit.reviewdb.client.Change; +import com.google.gerrit.server.project.SubmitRuleOptions; +import com.google.gerrit.server.query.change.ChangeData; +import com.google.gerrit.server.rules.PrologRuleEvaluator; +import com.google.gerrit.testing.TestChanges; +import com.google.inject.Inject; +import com.googlecode.prolog_cafe.lang.IntegerTerm; +import com.googlecode.prolog_cafe.lang.StructureTerm; +import com.googlecode.prolog_cafe.lang.Term; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import org.junit.Test; + +public class PrologRuleEvaluatorIT extends AbstractDaemonTest { + @Inject private PrologRuleEvaluator.Factory evaluatorFactory; + + @Test + public void convertsPrologToSubmitRecord() { + PrologRuleEvaluator evaluator = makeEvaluator(); + + StructureTerm verifiedLabel = makeLabel("Verified", "may"); + StructureTerm labels = new StructureTerm("label", verifiedLabel); + + List<Term> terms = ImmutableList.of(makeTerm("ok", labels)); + Collection<SubmitRecord> records = evaluator.resultsToSubmitRecord(null, terms); + + assertThat(records).hasSize(1); + } + + /** + * The Prolog behavior is everything but intuitive. Several submit_rules can be defined, and each + * will provide a different SubmitRecord answer when queried. The current implementation stops + * parsing the Prolog terms into SubmitRecord objects once it finds an OK record. This might lead + * to tangling results, as reproduced by this test. + * + * <p>Let's consider this rules.pl file (equivalent to the code in this test) + * + * <pre>{@code + * submit_rule(submit(R)) :- + * gerrit:uploader(U), + * R = label('Verified', reject(U)). + * + * submit_rule(submit(CR, V)) :- + * gerrit:uploader(U), + * V = label('Code-Review', ok(U)). + * + * submit_rule(submit(R)) :- + * gerrit:uploader(U), + * R = label('Any-Label-Name', reject(U)). + * }</pre> + * + * The first submit_rule always fails because the Verified label is rejected. + * + * <p>The second submit_rule is always valid, and provides two labels: OK and Code-Review. + * + * <p>The third submit_rule always fails because the Any-Label-Name label is rejected. + * + * <p>In this case, the last two SubmitRecords are used, the first one is discarded. + */ + @Test + public void abortsEarlyWithOkayRecord() { + PrologRuleEvaluator evaluator = makeEvaluator(); + + SubmitRecord.Label submitRecordLabel1 = new SubmitRecord.Label(); + submitRecordLabel1.label = "Verified"; + submitRecordLabel1.status = SubmitRecord.Label.Status.REJECT; + submitRecordLabel1.appliedBy = admin.id; + + SubmitRecord.Label submitRecordLabel2 = new SubmitRecord.Label(); + submitRecordLabel2.label = "Code-Review"; + submitRecordLabel2.status = SubmitRecord.Label.Status.OK; + submitRecordLabel2.appliedBy = admin.id; + + SubmitRecord.Label submitRecordLabel3 = new SubmitRecord.Label(); + submitRecordLabel3.label = "Any-Label-Name"; + submitRecordLabel3.status = SubmitRecord.Label.Status.REJECT; + submitRecordLabel3.appliedBy = user.id; + + List<Term> terms = new ArrayList<>(); + + StructureTerm label1 = makeLabel(submitRecordLabel1.label, "reject", admin); + + StructureTerm label2 = makeLabel(submitRecordLabel2.label, "ok", admin); + + StructureTerm label3 = makeLabel(submitRecordLabel3.label, "reject", user); + + terms.add(makeTerm("not_ready", makeLabels(label1))); + terms.add(makeTerm("ok", makeLabels(label2))); + terms.add(makeTerm("not_ready", makeLabels(label3))); + + // When + List<SubmitRecord> records = evaluator.resultsToSubmitRecord(null, terms); + + // assert that + SubmitRecord record1Expected = new SubmitRecord(); + record1Expected.status = SubmitRecord.Status.OK; + record1Expected.labels = new ArrayList<>(); + record1Expected.labels.add(submitRecordLabel2); + + SubmitRecord record2Expected = new SubmitRecord(); + record2Expected.status = SubmitRecord.Status.OK; + record2Expected.labels = new ArrayList<>(); + record2Expected.labels.add(submitRecordLabel3); + + assertThat(records).hasSize(2); + + assertThat(records.get(0)).isEqualTo(record1Expected); + assertThat(records.get(1)).isEqualTo(record2Expected); + } + + private static Term makeTerm(String status, StructureTerm labels) { + return new StructureTerm(status, labels); + } + + private static StructureTerm makeLabel(String name, String status) { + return new StructureTerm("label", new StructureTerm(name), new StructureTerm(status)); + } + + private static StructureTerm makeLabel(String name, String status, TestAccount account) { + StructureTerm user = new StructureTerm("user", new IntegerTerm(account.id.get())); + return new StructureTerm("label", new StructureTerm(name), new StructureTerm(status, user)); + } + + private static StructureTerm makeLabels(StructureTerm... labels) { + return new StructureTerm("label", labels); + } + + private ChangeData makeChangeData() { + ChangeData cd = ChangeData.createForTest(project, new Change.Id(1), 1); + cd.setChange(TestChanges.newChange(project, admin.id)); + return cd; + } + + private PrologRuleEvaluator makeEvaluator() { + return evaluatorFactory.create(makeChangeData(), SubmitRuleOptions.defaults()); + } +} |