eu.drus.jpa.unit.neo4j.dataset.GraphComparator Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of jpa-unit-neo4j Show documentation
Show all versions of jpa-unit-neo4j Show documentation
JUnit extension for simple testing of JPA entities and components
The newest version!
package eu.drus.jpa.unit.neo4j.dataset;
import static java.util.stream.Collectors.toList;
import static java.util.stream.Collectors.toSet;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.function.Function;
import org.jgrapht.Graph;
import eu.drus.jpa.unit.api.JpaUnitException;
import eu.drus.jpa.unit.spi.AssertionErrorCollector;
import eu.drus.jpa.unit.spi.ColumnsHolder;
public class GraphComparator {
private static final String FAILED_TO_VERIFY_DATA_BASE_STATE = "Failed to verify data base state";
private static final Function ID_MAPPER = (final String name) -> name.equalsIgnoreCase("ID") ? "id" : name;
private ColumnsHolder toExclude;
private boolean isStrict;
private DatabaseReader dbReader;
public GraphComparator(final GraphElementFactory factory, final String[] toExclude, final boolean strict) {
this.toExclude = new ColumnsHolder(toExclude, ID_MAPPER);
isStrict = strict;
dbReader = new DatabaseReader(factory);
}
public void compare(final Connection connection, final Graph expectedGraph, final AssertionErrorCollector errorCollector) {
Graph givenGraph;
try {
givenGraph = dbReader.readGraph(connection);
} catch (final SQLException e) {
throw new JpaUnitException(FAILED_TO_VERIFY_DATA_BASE_STATE, e);
}
if (expectedGraph.vertexSet().isEmpty()) {
shouldBeEmpty(givenGraph, errorCollector);
} else {
compareContent(givenGraph, expectedGraph, errorCollector);
}
}
private void shouldBeEmpty(final Graph givenGraph, final AssertionErrorCollector errorCollector) {
final Map unexpectedNodesOccurence = new HashMap<>();
for (final Node node : givenGraph.vertexSet()) {
unexpectedNodesOccurence.compute(node.getType(), (k, v) -> v == null ? 1 : v + 1);
}
for (final Entry nodeEntries : unexpectedNodesOccurence.entrySet()) {
if (nodeEntries.getValue() != 0) {
errorCollector.collect("No nodes with " + nodeEntries.getKey() + " labels were expected, but there are <"
+ nodeEntries.getValue() + "> nodes present.");
}
}
}
private void compareContent(final Graph givenGraph, final Graph expectedGraph,
final AssertionErrorCollector errorCollector) {
final Set expectedNodeTypes = expectedGraph.vertexSet().stream().map(Node::getType).collect(toSet());
final Set currentNodeTypes = givenGraph.vertexSet().stream().map(Node::getType).collect(toSet());
verifyNodeLabels(currentNodeTypes, expectedNodeTypes, errorCollector,
"Nodes with %s labels were expected to be present, but not found");
checkPresenceOfExpectedNodes(givenGraph, expectedGraph, errorCollector);
checkPresenceOfExpectedReferences(givenGraph, expectedGraph, errorCollector);
checkAbsenseOfNotExpectedNodes(givenGraph, expectedGraph, errorCollector);
checkAbsenseOfNotExpectedReferences(givenGraph, expectedGraph, errorCollector);
if (isStrict) {
verifyNodeLabels(expectedNodeTypes, currentNodeTypes, errorCollector,
"Nodes with %s labels were not expected, but are present");
}
}
private void verifyNodeLabels(final Collection currentNodeLabels, final Collection expectedNodeLabels,
final AssertionErrorCollector errorCollector, final String formatString) {
for (final String expectedNodeLabel : expectedNodeLabels) {
if (!currentNodeLabels.contains(expectedNodeLabel)) {
errorCollector.collect(String.format(formatString, expectedNodeLabel));
}
}
}
private void checkPresenceOfExpectedNodes(final Graph givenGraph, final Graph expectedGraph,
final AssertionErrorCollector errorCollector) {
for (final Node expectedNode : expectedGraph.vertexSet()) {
final List attributesToExclude = expectedNode.getLabels().stream().map(toExclude::getColumns).flatMap(List::stream)
.distinct().collect(toList());
final List availableNodesOfExpectedType = givenGraph.vertexSet().stream()
.filter(n -> n.getType().equals(expectedNode.getType())).collect(toList());
final List foundNodes = availableNodesOfExpectedType.stream().filter(n -> n.isSame(expectedNode, attributesToExclude))
.collect(toList());
if (foundNodes.isEmpty()) {
errorCollector.collect(expectedNode.asString() + " was expected, but is not present");
} else if (foundNodes.size() > 1) {
errorCollector.collect("Ambiguouty detected for node " + expectedNode.asString() + " for given attribute filter");
}
}
}
private void checkPresenceOfExpectedReferences(final Graph givenGraph, final Graph expectedGraph,
final AssertionErrorCollector errorCollector) {
for (final Edge expectedEdge : expectedGraph.edgeSet()) {
final List attributesToExclude = expectedEdge.getLabels().stream().map(toExclude::getColumns).flatMap(List::stream)
.distinct().collect(toList());
final List availableEdgesOfExpectedType = givenGraph.edgeSet().stream()
.filter(e -> e.getType().equals(expectedEdge.getType())).collect(toList());
final List foundEdges = availableEdgesOfExpectedType.stream().filter(e -> e.isSame(expectedEdge, attributesToExclude))
.collect(toList());
if (foundEdges.isEmpty()) {
errorCollector.collect(expectedEdge.asString() + " was expected, but is not present");
} else if (foundEdges.size() > 1) {
errorCollector.collect("Ambiguouty detected for edge " + expectedEdge.asString() + " for given attribute filter");
}
}
}
private void checkAbsenseOfNotExpectedNodes(final Graph givenGraph, final Graph expectedGraph,
final AssertionErrorCollector errorCollector) {
final List> expectedNodeLables = expectedGraph.vertexSet().stream().map(Node::getLabels).distinct().collect(toList());
for (final List labels : expectedNodeLables) {
final List expectedNodes = expectedGraph.vertexSet().stream().filter(node -> node.getLabels().containsAll(labels))
.collect(toList());
final List attributesToExclude = labels.stream().map(toExclude::getColumns).flatMap(List::stream).distinct()
.collect(toList());
for (final Node givenNode : givenGraph.vertexSet()) {
if (!givenNode.getLabels().containsAll(labels)) {
continue;
}
final boolean nodePresent = expectedNodes.stream().anyMatch(node -> {
final Set attributesToRetain = node.getAttributes().stream()
.filter(a -> !attributesToExclude.contains(a.getName())).collect(toSet());
return givenNode.getAttributes().containsAll(attributesToRetain);
});
if (!nodePresent) {
errorCollector.collect(givenNode.asString() + " was not expected, but is present");
}
}
}
}
private void checkAbsenseOfNotExpectedReferences(final Graph givenGraph, final Graph expectedGraph,
final AssertionErrorCollector errorCollector) {
final List> expectedEdgeLables = expectedGraph.edgeSet().stream().map(Edge::getLabels).distinct().collect(toList());
for (final List labels : expectedEdgeLables) {
final List expectedEdges = expectedGraph.edgeSet().stream().filter(node -> node.getLabels().containsAll(labels))
.collect(toList());
final List edgeAttributesToExclude = labels.stream().map(toExclude::getColumns).flatMap(List::stream).distinct()
.collect(toList());
for (final Edge givenEdge : givenGraph.edgeSet()) {
if (!givenEdge.getLabels().containsAll(labels)) {
continue;
}
final boolean edgePresent = expectedEdges.stream().anyMatch(edge -> {
final Set attributesToRetain = edge.getAttributes().stream()
.filter(a -> !edgeAttributesToExclude.contains(a.getName())).collect(toSet());
final List sourceNodeAttributesToExclude = edge.getSourceNode().getLabels().stream().map(toExclude::getColumns)
.flatMap(List::stream).distinct().collect(toList());
final List targetNodeAttributesToExclude = edge.getTargetNode().getLabels().stream().map(toExclude::getColumns)
.flatMap(List::stream).distinct().collect(toList());
return givenEdge.getAttributes().containsAll(attributesToRetain)
&& givenEdge.getSourceNode().isSame(edge.getSourceNode(), sourceNodeAttributesToExclude)
&& givenEdge.getTargetNode().isSame(edge.getTargetNode(), targetNodeAttributesToExclude);
});
if (!edgePresent) {
errorCollector.collect(givenEdge.asString() + " was not expected, but is present");
}
}
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy