package rtt.core.testing.compare;
import java.util.ArrayList;
import java.util.List;
import rtt.core.archive.output.Element;
import rtt.core.archive.output.Output;
import rtt.core.testing.compare.OutputCompare.CompareResult.Difference;
import rtt.core.testing.compare.results.TestFailure;
public class OutputCompare {
public static class CompareResult {
public enum Difference {
ELEMENT_TYPE("Element type"),
GENERATOR_TYPE("Generated by"),
INFORMATIONAL("IsInformational"),
NAME("Name"),
VALUE("Value"),
CHILD_COUNT("Sizes of children");
private String description;
private Difference(String description) {
this.description = description;
}
}
private Difference difference = null;
private Object expected = null;
private Object actual = null;
protected CompareResult(Difference difference) {
this.difference = difference;
}
public Difference getDifference() {
return difference;
}
public boolean hasDifferences() {
return difference != null;
}
public String getMessage() {
if (difference != null) {
StringBuilder builder = new StringBuilder(difference.description);
if (expected != null && actual != null) {
builder.append(" expected '");
builder.append(expected.toString());
builder.append("', but was '");
builder.append(actual.toString());
builder.append("'.");
}
return builder.toString();
}
return "No differences found.";
}
public static CompareResult create(Difference difference, Object expected, Object actual) {
CompareResult result = new CompareResult(difference);
result.difference = difference;
result.expected = expected;
result.actual = actual;
return result;
}
}
private static final String ELEMENT_NULL =
"One or both given elements were null.";
private boolean testInformational;
public OutputCompare(boolean testInformational) {
this.testInformational = testInformational;
}
public static List<TestFailure> compareOutput(
Output referenceOutput, Output actualOutput, boolean testInformational) {
if (referenceOutput == null || actualOutput == null) {
throw new IllegalArgumentException("Reference or actual output was null.");
}
List<TestFailure> failures = new ArrayList<>();
Element refInitElement = referenceOutput.getInitialElement();
Element actualInitElement = actualOutput.getInitialElement();
if (refInitElement != null && actualInitElement != null) {
OutputCompare comparer = new OutputCompare(testInformational);
CompareResult result = comparer.compareElements(
refInitElement, actualInitElement);
if (result != null && result.hasDifferences()) {
failures.add(new TestFailure(result.getMessage()));
}
} else if (refInitElement != actualInitElement) {
failures.add(new TestFailure("Initial elements are different."));
}
return failures;
}
public CompareResult compareElements(Element referenceElement, Element actualElement) {
if (referenceElement == null || actualElement == null) {
throw new IllegalArgumentException(ELEMENT_NULL);
}
if (!referenceElement.getElementType().equals(actualElement.getElementType())) {
return CompareResult.create(Difference.ELEMENT_TYPE,
referenceElement.getElementType().name(),
actualElement.getElementType().name());
}
if (!referenceElement.getGeneratedBy().equals(actualElement.getGeneratedBy())) {
return CompareResult.create(Difference.GENERATOR_TYPE,
referenceElement.getGeneratedBy().name(),
actualElement.getGeneratedBy().name());
}
if (!referenceElement.getName().equals(actualElement.getName())) {
return CompareResult.create(Difference.NAME,
referenceElement.getName(), actualElement.getName());
}
if (referenceElement.isInformational() != actualElement.isInformational()) {
return CompareResult.create(Difference.INFORMATIONAL,
referenceElement.isInformational(), actualElement.isInformational());
}
if (testInformational(referenceElement)) {
String valueOfRefer = String.valueOf(referenceElement.getValue());
String valueOfActual = String.valueOf(actualElement.getValue());
if (!valueOfRefer.equals(valueOfActual)) {
return CompareResult.create(Difference.VALUE, valueOfRefer, valueOfActual);
}
List<Element> referenceCompareElements = referenceElement.getElements();
List<Element> actualCompareElements = actualElement.getElements();
if (testInformational == false) {
referenceCompareElements = getCompareElements(referenceCompareElements);
actualCompareElements = getCompareElements(actualCompareElements);
}
return compareChildElements(referenceCompareElements, actualCompareElements);
}
return null;
}
private boolean hasDifferences(CompareResult result) {
return result != null && result.hasDifferences();
}
private boolean testInformational(Element element) {
return !element.isInformational() || testInformational;
}
private List<Element> getCompareElements(List<Element> refValues) {
List<Element> compareElements = new ArrayList<>();
for (Element element : refValues) {
if (!element.isInformational()) {
compareElements.add(element);
}
}
return compareElements;
}
private CompareResult compareChildElements(
List<Element> refElements, List<Element> actualElements) {
if (refElements.size() != actualElements.size()) {
return CompareResult.create(Difference.CHILD_COUNT,
refElements.size(), actualElements.size());
}
int childCount = refElements.size();
for (int index = 0; index < childCount; index++) {
Element referenceElement = refElements.get(index);
Element actualElement = actualElements.get(index);
CompareResult result = compareElements(
referenceElement, actualElement);
if (hasDifferences(result)) {
return result;
}
}
return null;
}
}