/** * Copyright (c) 2011 Cloudsmith Inc. and other contributors, as listed below. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Cloudsmith * */ package org.cloudsmith.geppetto.validation.tests; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map.Entry; import junit.framework.ComparisonFailure; import org.cloudsmith.geppetto.diagnostic.DetailedFileDiagnostic; import org.cloudsmith.geppetto.diagnostic.Diagnostic; import org.cloudsmith.geppetto.diagnostic.FileDiagnostic; import com.google.common.base.Joiner; import com.google.common.base.Predicate; import com.google.common.collect.Iterables; /** * Helper class making it easier to assert content of a BasicDiagnostic * */ public class DiagnosticsAsserter { public interface DiagnosticPredicate extends Predicate<Diagnostic> { public DiagnosticPredicate greedy(); public boolean isGreedy(); public boolean isRequired(); public DiagnosticPredicate optional(); } protected static class IssuePredicate implements DiagnosticPredicate { protected String issueCode; protected boolean optional; protected boolean greedy; protected String msg; public IssuePredicate(String issueCode) { this(issueCode, null); } public IssuePredicate(String issueCode, String msg) { this.issueCode = issueCode; this.msg = msg; this.optional = false; this.greedy = false; } public boolean apply(Diagnostic d) { if(msg != null && d.getMessage() != null && !d.getMessage().contains(msg)) return false; return issueCode == null || issueCode.equals(d.getIssue()); } public IssuePredicate greedy() { this.greedy = true; return this; } public boolean isGreedy() { return greedy; } public boolean isRequired() { return !optional; } public IssuePredicate optional() { this.optional = true; return this; } @Override public String toString() { List<String> r = new ArrayList<String>(); if(issueCode != null) r.add("issueCode=" + issueCode); if(msg != null) r.add("msgFragment='" + msg + "'"); return "(" + Joiner.on(" ").join(r) + ")"; } } private Diagnostic diagnostics; public DiagnosticsAsserter(Diagnostic diag) { diagnostics = diag; } public void assertAll(DiagnosticPredicate... predicates) { assertAll(getAllDiagnostics(), predicates); } public void assertAll(Iterable<Diagnostic> asserted, DiagnosticPredicate predicates[]) { HashMap<DiagnosticPredicate, Boolean> consumed = new HashMap<DiagnosticPredicate, Boolean>(); for(DiagnosticPredicate p : predicates) consumed.put(p, Boolean.FALSE); for(Diagnostic d : asserted) { boolean found = false; for(Entry<DiagnosticPredicate, Boolean> e : consumed.entrySet()) if((!e.getValue() || e.getKey().isGreedy()) && e.getKey().apply(d)) { consumed.put(e.getKey(), Boolean.TRUE); found = true; break; } if(!found) { if(predicates.length == 1) throw new ComparisonFailure( "Predicate does not match", predicates[0].toString(), diagnosticsToString(d)); throw new ComparisonFailure( "No predicate in expected matches", Arrays.toString(predicates), diagnosticsToString(d)); } } ArrayList<DiagnosticPredicate> unconsumed = new ArrayList<DiagnosticPredicate>(); for(Entry<DiagnosticPredicate, Boolean> e : consumed.entrySet()) if(!e.getValue() && e.getKey().isRequired()) unconsumed.add(e.getKey()); if(unconsumed.size() != 0) throw new ComparisonFailure( "Missing diagnostics for required predicates", Arrays.toString(unconsumed.toArray()), diagnosticsToString(asserted)); } public void assertAny(Iterable<Diagnostic> asserted, DiagnosticPredicate... predicates) { for(DiagnosticPredicate predicate : predicates) if(Iterables.any(asserted, predicate)) return; throw new ComparisonFailure( "No predicate (any expected) matches diagnostics", Arrays.toString(predicates), diagnosticsToString(asserted)); } /** * Warnings and/or errors must be present. */ public void assertDiagnostics() { if(diagnostics.getChildren().size() < 1) throw new ComparisonFailure("Diagnostics expected", "> 0 Diagnostics", ""); } public void assertErrors(DiagnosticPredicate... predicates) { assertAll(getErrorDiagnostics(), predicates); } /** * No errors or warnings accepted. * * @param message * @param diag */ public void assertOk() { if(diagnostics.getChildren().size() > 0) throw new ComparisonFailure( "No diagnostics expected", "No diagnostics", diagnosticsToString(diagnostics.getChildren())); } public void assertWarnings(DiagnosticPredicate... predicates) { assertAll(getWarningDiagnostics(), predicates); } public String diagnosticsToString(Diagnostic d) { StringBuilder builder = new StringBuilder(); builder.append(d.toString()); builder.append("\n"); return builder.toString(); } public String diagnosticsToString(Iterable<Diagnostic> diag) { StringBuilder builder = new StringBuilder(); for(Diagnostic d : diag) { builder.append("issueCode="); builder.append(d.getIssue()); builder.append(" msg='"); builder.append(d.getMessage()); builder.append('\''); if(d instanceof FileDiagnostic) { FileDiagnostic fd = (FileDiagnostic) d; builder.append(" file="); builder.append(fd.getFile()); builder.append(" line="); builder.append(fd.getLineNumber()); if(fd instanceof DetailedFileDiagnostic) { DetailedFileDiagnostic dfd = (DetailedFileDiagnostic) fd; builder.append(" offset="); builder.append(dfd.getOffset()); builder.append(" length="); builder.append(dfd.getLength()); } } else builder.append(d.toString()); builder.append("\n"); } return builder.toString(); } public Iterable<Diagnostic> getAllDiagnostics() { return diagnostics; } public Iterable<Diagnostic> getErrorDiagnostics() { return severityIterable(Diagnostic.ERROR, diagnostics); } public Iterable<Diagnostic> getWarningDiagnostics() { return severityIterable(Diagnostic.WARNING, diagnostics); } public DiagnosticPredicate issue(String issueCode) { return new IssuePredicate(issueCode, null); } public DiagnosticPredicate issue(String issueCode, String messageFragment) { return new IssuePredicate(issueCode, messageFragment); } public DiagnosticPredicate messageFragment(String messageFragment) { return new IssuePredicate(null, messageFragment); } private Iterable<Diagnostic> severityIterable(final int severity, Diagnostic diag) { return Iterables.filter(diag, new Predicate<Diagnostic>() { @Override public boolean apply(Diagnostic input) { return input.getSeverity() == severity; } }); } }