package hudson.plugins.cigame.rules.unittesting; import java.util.Collection; import hudson.model.AbstractBuild; import hudson.model.Result; import hudson.plugins.cigame.model.AggregatableRule; import hudson.plugins.cigame.model.RuleResult; import hudson.tasks.test.AbstractTestResultAction; public abstract class AbstractUnitTestsRule implements AggregatableRule<Integer> { @SuppressWarnings("unchecked") static final AbstractTestResultAction ZERO_RESULT = new AbstractTestResultAction(null) { @Override public int getFailCount() { return 0; } @Override public Object getResult() { return null; } @Override public int getTotalCount() { return 0; } @Override public int getSkipCount() { return 0; } }; /** * Returns the youngest build which is usable to compare the current test result against. * I.e. returns the youngest build which is better than NOT_BUILD and has test results. * FAILURE builds are returned immediately! * * @return the previous build or null if no such build was found */ private AbstractBuild<?, ?> getPreviousBuildWithResults(AbstractBuild<?, ?> previousBuild) { while(previousBuild != null) { if (previousBuild.getResult() != null) { if (previousBuild.getResult().isBetterThan(Result.FAILURE)) { @SuppressWarnings("unchecked") AbstractTestResultAction action = previousBuild.getAction(AbstractTestResultAction.class); if (action != null) { return previousBuild; } // fall through } else if (previousBuild.getResult().isWorseOrEqualTo(Result.NOT_BUILT)) { // fall through } else { return previousBuild; } } previousBuild = previousBuild.getPreviousBuild(); } return null; } @SuppressWarnings("unchecked") public final RuleResult<Integer> evaluate(AbstractBuild<?, ?> previousBuild, AbstractBuild<?, ?> build) { previousBuild = getPreviousBuildWithResults(previousBuild); AbstractTestResultAction action; AbstractTestResultAction prevAction; Result result; Result prevResult; if (previousBuild == null && build == null) { return null; } if (build == null) { action = null; result = Result.SUCCESS; } else { action = build.getAction(AbstractTestResultAction.class); result = build.getResult(); } if (previousBuild == null) { prevAction = ZERO_RESULT; prevResult = Result.SUCCESS; } else { prevAction = previousBuild.getAction(AbstractTestResultAction.class); prevResult = previousBuild.getResult(); } prevAction = prevAction != null ? prevAction : ZERO_RESULT; // sometimes (when a build is aborted?) result can be null prevResult = prevResult != null ? prevResult : Result.ABORTED; result = result != null ? result : Result.ABORTED; // if the current action is null, let's assume as a ZERO result action = action != null ? action : ZERO_RESULT; if ((prevResult.isBetterThan(Result.FAILURE)) && (result.isBetterThan(Result.FAILURE))) { return evaluate(action, prevAction); } else { return null; } } @Override public final RuleResult<?> aggregate(Collection<RuleResult<Integer>> results) { double score = 0.0; int testDiff = 0; for (RuleResult<Integer> result : results) { if (result != null) { score += result.getPoints(); testDiff += result.getAdditionalData(); } } if (score != 0.0) { return new RuleResult<Void>(score, getResultDescription(testDiff)); } return null; } public final RuleResult<Integer> evaluate(AbstractBuild<?, ?> build) { throw new UnsupportedOperationException(); } protected abstract String getResultDescription(Integer testDiff); protected abstract RuleResult<Integer> evaluate( AbstractTestResultAction<?> testResult, AbstractTestResultAction<?> previousTestResult); }