Make SubmitRuleEvaluator usable for testing prolog rules.
For the purpose of testing submit rules the SubmitRuleEvaluator needs more flexibility like skipping the submit filters and loading prolog rules from a caller provided input stream. This change is a preparation for refactoring of the test-submit-rule command which currently duplicates most of the code for finding and executing the prolog rules. Change-Id: I54086590fa5dc5cefdd9c36ca2e8587d374bd988 Signed-off-by: Sasa Zivkov <sasa.zivkov@sap.com>
This commit is contained in:
@@ -29,6 +29,7 @@ import com.googlecode.prolog_cafe.lang.PrologException;
|
||||
import com.googlecode.prolog_cafe.lang.Term;
|
||||
import com.googlecode.prolog_cafe.lang.VariableTerm;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
@@ -53,6 +54,8 @@ public class SubmitRuleEvaluator {
|
||||
private final String userRuleWrapperName;
|
||||
private final String filterRuleLocatorName;
|
||||
private final String filterRuleWrapperName;
|
||||
private final boolean skipFilters;
|
||||
private final InputStream rulesInputStream;
|
||||
|
||||
private Term submitRule;
|
||||
private String projectName;
|
||||
@@ -67,12 +70,38 @@ public class SubmitRuleEvaluator {
|
||||
* @param filterRuleWrapperName The name of the rule used to evaluate the
|
||||
* filter rule.
|
||||
*/
|
||||
SubmitRuleEvaluator(ReviewDb db, PatchSet patchSet,
|
||||
public SubmitRuleEvaluator(ReviewDb db, PatchSet patchSet,
|
||||
ProjectControl projectControl,
|
||||
ChangeControl changeControl, Change change, @Nullable ChangeData cd,
|
||||
boolean fastEvalLabels,
|
||||
String userRuleLocatorName, String userRuleWrapperName,
|
||||
String filterRuleLocatorName, String filterRuleWrapperName) {
|
||||
this(db, patchSet, projectControl, changeControl, change, cd,
|
||||
fastEvalLabels, userRuleLocatorName, userRuleWrapperName,
|
||||
filterRuleLocatorName, filterRuleWrapperName, false, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param userRuleLocatorName The name of the rule used to locate the
|
||||
* user-supplied rule.
|
||||
* @param userRuleWrapperName The name of the wrapper rule used to evaluate
|
||||
* the user-supplied rule.
|
||||
* @param filterRuleLocatorName The name of the rule used to locate the filter
|
||||
* rule.
|
||||
* @param filterRuleWrapperName The name of the rule used to evaluate the
|
||||
* filter rule.
|
||||
* @param skipSubmitFilters if <code>true</code> submit filter will not be
|
||||
* applied
|
||||
* @param rules when non-null the rules will be read from this input stream
|
||||
* instead of refs/meta/config:rules.pl file
|
||||
*/
|
||||
public SubmitRuleEvaluator(ReviewDb db, PatchSet patchSet,
|
||||
ProjectControl projectControl,
|
||||
ChangeControl changeControl, Change change, @Nullable ChangeData cd,
|
||||
boolean fastEvalLabels,
|
||||
String userRuleLocatorName, String userRuleWrapperName,
|
||||
String filterRuleLocatorName, String filterRuleWrapperName,
|
||||
boolean skipSubmitFilters, InputStream rules) {
|
||||
this.db = db;
|
||||
this.patchSet = patchSet;
|
||||
this.projectControl = projectControl;
|
||||
@@ -84,6 +113,8 @@ public class SubmitRuleEvaluator {
|
||||
this.userRuleWrapperName = userRuleWrapperName;
|
||||
this.filterRuleLocatorName = filterRuleLocatorName;
|
||||
this.filterRuleWrapperName = filterRuleWrapperName;
|
||||
this.skipFilters = skipSubmitFilters;
|
||||
this.rulesInputStream = rules;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -96,25 +127,10 @@ public class SubmitRuleEvaluator {
|
||||
* @return List of {@link Term} objects returned from the evaluated rules.
|
||||
* @throws RuleEvalException
|
||||
*/
|
||||
ListTerm evaluate() throws RuleEvalException {
|
||||
public ListTerm evaluate() throws RuleEvalException {
|
||||
List<Term> results = new ArrayList<Term>();
|
||||
ProjectState projectState = projectControl.getProjectState();
|
||||
PrologEnvironment env;
|
||||
|
||||
PrologEnvironment env = getPrologEnvironment();
|
||||
try {
|
||||
env = projectState.newPrologEnvironment();
|
||||
} catch (CompileException err) {
|
||||
throw new RuleEvalException("Cannot consult rules.pl for "
|
||||
+ getProjectName(), err);
|
||||
}
|
||||
|
||||
try {
|
||||
env.set(StoredValues.REVIEW_DB, db);
|
||||
env.set(StoredValues.CHANGE, change);
|
||||
env.set(StoredValues.CHANGE_DATA, cd);
|
||||
env.set(StoredValues.PATCH_SET, patchSet);
|
||||
env.set(StoredValues.CHANGE_CONTROL, changeControl);
|
||||
|
||||
submitRule = env.once("gerrit", userRuleLocatorName, new VariableTerm());
|
||||
if (fastEvalLabels) {
|
||||
env.once("gerrit", "assume_range_from_label");
|
||||
@@ -135,57 +151,86 @@ public class SubmitRuleEvaluator {
|
||||
err);
|
||||
}
|
||||
|
||||
ProjectState parentState = projectState.getParentState();
|
||||
PrologEnvironment childEnv = env;
|
||||
Set<Project.NameKey> projectsSeen = new HashSet<Project.NameKey>();
|
||||
projectsSeen.add(projectState.getProject().getNameKey());
|
||||
|
||||
Term resultsTerm = toListTerm(results);
|
||||
while (parentState != null) {
|
||||
if (!projectsSeen.add(parentState.getProject().getNameKey())) {
|
||||
// parent has been seen before, stop walk up inheritance tree
|
||||
break;
|
||||
}
|
||||
PrologEnvironment parentEnv;
|
||||
try {
|
||||
parentEnv = parentState.newPrologEnvironment();
|
||||
} catch (CompileException err) {
|
||||
throw new RuleEvalException("Cannot consult rules.pl for "
|
||||
+ parentState.getProject().getName(), err);
|
||||
}
|
||||
|
||||
parentEnv.copyStoredValues(childEnv);
|
||||
Term filterRule =
|
||||
parentEnv.once("gerrit", filterRuleLocatorName, new VariableTerm());
|
||||
try {
|
||||
if (fastEvalLabels) {
|
||||
env.once("gerrit", "assume_range_from_label");
|
||||
}
|
||||
|
||||
Term[] template =
|
||||
parentEnv.once("gerrit", filterRuleWrapperName, filterRule,
|
||||
resultsTerm, new VariableTerm());
|
||||
resultsTerm = template[2];
|
||||
} catch (PrologException err) {
|
||||
throw new RuleEvalException("Exception calling " + filterRule
|
||||
+ " on change " + change.getId() + " of "
|
||||
+ parentState.getProject().getName(), err);
|
||||
} catch (RuntimeException err) {
|
||||
throw new RuleEvalException("Exception calling " + filterRule
|
||||
+ " on change " + change.getId() + " of "
|
||||
+ parentState.getProject().getName(), err);
|
||||
}
|
||||
|
||||
parentState = parentState.getParentState();
|
||||
childEnv = parentEnv;
|
||||
if (!skipFilters) {
|
||||
resultsTerm = runSubmitFilters(resultsTerm, env);
|
||||
}
|
||||
|
||||
return (ListTerm) resultsTerm;
|
||||
} finally {
|
||||
env.close();
|
||||
}
|
||||
}
|
||||
|
||||
private PrologEnvironment getPrologEnvironment() throws RuleEvalException {
|
||||
ProjectState projectState = projectControl.getProjectState();
|
||||
PrologEnvironment env;
|
||||
try {
|
||||
if (rulesInputStream == null) {
|
||||
env = projectState.newPrologEnvironment();
|
||||
} else {
|
||||
env = projectState.newPrologEnvironment("stdin", rulesInputStream);
|
||||
}
|
||||
} catch (CompileException err) {
|
||||
throw new RuleEvalException("Cannot consult rules.pl for "
|
||||
+ getProjectName(), err);
|
||||
}
|
||||
env.set(StoredValues.REVIEW_DB, db);
|
||||
env.set(StoredValues.CHANGE, change);
|
||||
env.set(StoredValues.CHANGE_DATA, cd);
|
||||
env.set(StoredValues.PATCH_SET, patchSet);
|
||||
env.set(StoredValues.CHANGE_CONTROL, changeControl);
|
||||
return env;
|
||||
}
|
||||
|
||||
private Term runSubmitFilters(Term results, PrologEnvironment env) throws RuleEvalException {
|
||||
ProjectState projectState = projectControl.getProjectState();
|
||||
ProjectState parentState = projectState.getParentState();
|
||||
PrologEnvironment childEnv = env;
|
||||
Set<Project.NameKey> projectsSeen = new HashSet<Project.NameKey>();
|
||||
projectsSeen.add(projectState.getProject().getNameKey());
|
||||
|
||||
while (parentState != null) {
|
||||
if (!projectsSeen.add(parentState.getProject().getNameKey())) {
|
||||
// parent has been seen before, stop walk up inheritance tree
|
||||
break;
|
||||
}
|
||||
PrologEnvironment parentEnv;
|
||||
try {
|
||||
parentEnv = parentState.newPrologEnvironment();
|
||||
} catch (CompileException err) {
|
||||
throw new RuleEvalException("Cannot consult rules.pl for "
|
||||
+ parentState.getProject().getName(), err);
|
||||
}
|
||||
|
||||
parentEnv.copyStoredValues(childEnv);
|
||||
Term filterRule =
|
||||
parentEnv.once("gerrit", filterRuleLocatorName, new VariableTerm());
|
||||
try {
|
||||
if (fastEvalLabels) {
|
||||
env.once("gerrit", "assume_range_from_label");
|
||||
}
|
||||
|
||||
Term[] template =
|
||||
parentEnv.once("gerrit", filterRuleWrapperName, filterRule,
|
||||
results, new VariableTerm());
|
||||
results = template[2];
|
||||
} catch (PrologException err) {
|
||||
throw new RuleEvalException("Exception calling " + filterRule
|
||||
+ " on change " + change.getId() + " of "
|
||||
+ parentState.getProject().getName(), err);
|
||||
} catch (RuntimeException err) {
|
||||
throw new RuleEvalException("Exception calling " + filterRule
|
||||
+ " on change " + change.getId() + " of "
|
||||
+ parentState.getProject().getName(), err);
|
||||
}
|
||||
|
||||
parentState = parentState.getParentState();
|
||||
childEnv = parentEnv;
|
||||
}
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
private static Term toListTerm(List<Term> terms) {
|
||||
Term list = Prolog.Nil;
|
||||
for (int i = terms.size() - 1; i >= 0; i--) {
|
||||
@@ -194,7 +239,7 @@ public class SubmitRuleEvaluator {
|
||||
return list;
|
||||
}
|
||||
|
||||
Term getSubmitRule() {
|
||||
public Term getSubmitRule() {
|
||||
return submitRule;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user