From 5808ab3881a276a825059b708e26dd428caddc7c Mon Sep 17 00:00:00 2001 From: heinpa Date: Tue, 5 Mar 2024 13:54:29 +0100 Subject: [PATCH 1/2] add tests for content of generated queries --- qanary_commons/pom.xml | 2 +- .../test/java/qa/commons/QanaryQueryTest.java | 215 ++++++++++++++++++ 2 files changed, 216 insertions(+), 1 deletion(-) create mode 100644 qanary_commons/src/test/java/qa/commons/QanaryQueryTest.java diff --git a/qanary_commons/pom.xml b/qanary_commons/pom.xml index 59f108b5..77fd3fcb 100644 --- a/qanary_commons/pom.xml +++ b/qanary_commons/pom.xml @@ -6,7 +6,7 @@ org.springframework.boot spring-boot-starter-parent - 2.6.7 + 2.7.0 diff --git a/qanary_commons/src/test/java/qa/commons/QanaryQueryTest.java b/qanary_commons/src/test/java/qa/commons/QanaryQueryTest.java new file mode 100644 index 00000000..5f2da380 --- /dev/null +++ b/qanary_commons/src/test/java/qa/commons/QanaryQueryTest.java @@ -0,0 +1,215 @@ +package qa.commons; + +import static java.util.Map.entry; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; + +import org.apache.jena.graph.impl.LiteralLabel; +import org.apache.jena.query.Query; +import org.apache.jena.query.QueryFactory; +import org.apache.jena.shared.impl.PrefixMappingImpl; +import org.apache.jena.sparql.algebra.Algebra; +import org.apache.jena.sparql.algebra.Op; +import org.apache.jena.sparql.algebra.OpAsQuery; +import org.apache.jena.sparql.core.TriplePath; +import org.apache.jena.sparql.syntax.ElementFilter; +import org.apache.jena.sparql.syntax.ElementPathBlock; +import org.apache.jena.sparql.syntax.ElementVisitorBase; +import org.apache.jena.sparql.syntax.ElementWalker; + + +public class QanaryQueryTest { + + // static default prefixMapping that may be used to instantiate these Tests + public static Map COMMON_PREFIXES = Map.ofEntries( + entry("oa", "http://www.w3.org/ns/openannotation/core/"), + entry("wdt", "http://www.wikidata.org/prop/direct/"), + entry("rdfs", "http://www.w3.org/2000/01/rdf-schema#"), + entry("bd", "http://www.bigdata.com/rdf#"), + entry("wikibase", "http://wikiba.se/ontology#") + ); + + private final PrefixMappingImpl prefixMapping; + + /** + * Use QanaryQueryTest.COMMON_PREFIXES or define your own prefix mappings. + * + * @param prefixMapping + */ + public QanaryQueryTest(Map prefixMapping) { + this.prefixMapping = new PrefixMappingImpl(); + this.prefixMapping.setNsPrefixes(prefixMapping); + } + + // + // TEST METHODS + // + + /** + * Assert that two supplied queries have equal string representations. + * + * @param queryString + * @param expectedGraph + */ + public void isSparqlQueryEqual(String expectedQueryString, String actualQueryString) { + Query expectedParsedQuery = QueryFactory.create(expectedQueryString); + Op expectedOp = Algebra.compile(expectedParsedQuery); + Query expectedQueryAlgebra = OpAsQuery.asQuery(expectedOp); + + Query actualParsedQuery = QueryFactory.create(actualQueryString); + Op actualOp = Algebra.compile(actualParsedQuery); + Query actualQueryAlgebra = OpAsQuery.asQuery(actualOp); + + assertEquals(expectedQueryAlgebra.serialize(), actualQueryAlgebra.serialize(), + "The queries do not match"); + } + + /** + * Assert that the supplied query contains a specific graph. + * + * @param queryString + * @param expectedGraph + */ + public void queryContainsGraph(String queryString, String expectedGraph) { + ParsedQueryContent parsedQueryContent = this.parseQueryContent(queryString); + assertTrue(parsedQueryContent.getGraphs().stream().anyMatch( + o -> expectedGraph.equals(o.toString())), + "The query does not contain the specified graph"); + } + + /** + * Assert that the supplied query contains a FILTER statement with specific key and value. + * + * @param queryString + * @param expectedKey a variable name + * @param expectedValue a URI or literal as String + */ + public void queryContainsFilterKeyValuePair(String queryString, String expectedKey, String expectedValue) { + ParsedQueryContent parsedQueryContent = this.parseQueryContent(queryString); + assertTrue(parsedQueryContent.getFilters().stream().anyMatch( + o -> (o.toString().contains(expectedKey) + && o.toString().contains(expectedValue))), + "The query does not contain a FILTER statement with the specified key-value pair"); + } + + /** + * Assert that the supplied query contains a specific triple. + * + * @param queryString + * @param subject a literal with lexical form, datatype IRI and optionally a language tag + * @param predicate a URI string or variable + * @param object a URI string or variable name + */ + public void queryContainsTriple(String queryString, String subject, String predicate, String object) { + ParsedQueryContent parsedQueryContent = this.parseQueryContent(queryString); + assertTrue(parsedQueryContent.getTriples().stream().anyMatch( + o -> (subject.equals(o.getSubject().toString(this.prefixMapping))) + && predicate.equals(o.getPredicate().toString(this.prefixMapping)) + && object.equals(o.getObject().toString(this.prefixMapping))), + "The query does not contain the specified triple"); + } + + /** + * Assert that the supplied query contains a specific triple. + * + * @param queryString + * @param subject a URI string or variable name + * @param predicate a URI string or variable name + * @param object a literal with lexical form, datatype IRI and optionally a language tag + */ + public void queryContainsTriple(String queryString, String subject, String predicate, LiteralLabel object) { + ParsedQueryContent parsedQueryContent = this.parseQueryContent(queryString); + assertTrue(parsedQueryContent.getTriples().stream().anyMatch( + o -> (subject.equals(o.getSubject().toString(this.prefixMapping))) + && predicate.equals(o.getPredicate().toString(this.prefixMapping)) + && object.equals(o.getObject().getLiteral())), + "The query does not contain the specified triple"); + } + + /** + * Assert that the supplied query contains a specific triple. + * + * @param queryString + * @param subject a URI string or variable name + * @param predicate a URI string or variable name + * @param object a URI string or variable name + */ + public void queryContainsTriple(String queryString, LiteralLabel subject, String predicate, String object) { + ParsedQueryContent parsedQueryContent = this.parseQueryContent(queryString); + assertTrue(parsedQueryContent.getTriples().stream().anyMatch( + o -> (subject.equals(o.getSubject().getLiteral())) + && predicate.equals(o.getPredicate().toString(this.prefixMapping)) + && object.equals(o.getObject().toString(this.prefixMapping))), + "The query does not contain the specified triple"); + + } + + // TODO: consider methods for complete list matches + //public boolean containsAllGraphs(List expectedGraphs) { + // return CollectionUtils.isEqualCollection(this.graphs, expectedGraphs); + //} + // public boolean containsAllFilterKeyValuePairs() {} + // public boolean containsAllTriples() {} + + // + // CONTENT PARSING + // + + // parses the query to extract graphs, filters and triples + private ParsedQueryContent parseQueryContent(String queryString) { + List graphs = new LinkedList<>(); + List filters = new LinkedList<>(); + List triples = new LinkedList<>(); + + Query query = QueryFactory.create(queryString); + graphs = query.getGraphURIs(); + ElementWalker.walk(query.getQueryPattern(), + new ElementVisitorBase() { + // for visiting Filter statements + public void visit(ElementFilter filter) { + filters.add(filter.getExpr().toString()); + } + // for visiting a block of Triples + public void visit(ElementPathBlock el) { + // iterate of all Triples in the block + Iterator triplePaths = el.patternElts(); + while (triplePaths.hasNext()) { + TriplePath triple = triplePaths.next(); + triples.add(triple); + } + } + } + ); + return new ParsedQueryContent(graphs, filters, triples); + } + + // holds parsed query elements + private class ParsedQueryContent { + private List graphs = new LinkedList<>(); + private List filters = new LinkedList<>(); + private List triples = new LinkedList<>(); + + public ParsedQueryContent(List graphs, List filters, List triples) { + this.graphs = graphs; + this.filters = filters; + this.triples = triples; + } + + public List getGraphs() { + return graphs; + } + + public List getFilters() { + return filters; + } + + public List getTriples() { + return triples; + } + } +} From 03ebe87c61cf3ab2c8164e3279f8c98acee1d81f Mon Sep 17 00:00:00 2001 From: heinpa Date: Fri, 16 Aug 2024 12:38:21 +0200 Subject: [PATCH 2/2] update javadoc --- .../test/java/qa/commons/QanaryQueryTest.java | 23 ++++++++----------- 1 file changed, 9 insertions(+), 14 deletions(-) diff --git a/qanary_commons/src/test/java/qa/commons/QanaryQueryTest.java b/qanary_commons/src/test/java/qa/commons/QanaryQueryTest.java index 5f2da380..db4ab127 100644 --- a/qanary_commons/src/test/java/qa/commons/QanaryQueryTest.java +++ b/qanary_commons/src/test/java/qa/commons/QanaryQueryTest.java @@ -37,9 +37,7 @@ public class QanaryQueryTest { private final PrefixMappingImpl prefixMapping; /** - * Use QanaryQueryTest.COMMON_PREFIXES or define your own prefix mappings. - * - * @param prefixMapping + * @param prefixMapping use QanaryQueryTest.COMMON_PREFIXES or define your own prefix mappings. */ public QanaryQueryTest(Map prefixMapping) { this.prefixMapping = new PrefixMappingImpl(); @@ -101,8 +99,8 @@ public void queryContainsFilterKeyValuePair(String queryString, String expectedK * Assert that the supplied query contains a specific triple. * * @param queryString - * @param subject a literal with lexical form, datatype IRI and optionally a language tag - * @param predicate a URI string or variable + * @param subject a URI string or variable name + * @param predicate a URI string or variable name * @param object a URI string or variable name */ public void queryContainsTriple(String queryString, String subject, String predicate, String object) { @@ -135,7 +133,7 @@ public void queryContainsTriple(String queryString, String subject, String predi * Assert that the supplied query contains a specific triple. * * @param queryString - * @param subject a URI string or variable name + * @param subject a literal with lexical form, datatype IRI and optionally a language tag * @param predicate a URI string or variable name * @param object a URI string or variable name */ @@ -149,18 +147,15 @@ public void queryContainsTriple(String queryString, LiteralLabel subject, String } - // TODO: consider methods for complete list matches - //public boolean containsAllGraphs(List expectedGraphs) { - // return CollectionUtils.isEqualCollection(this.graphs, expectedGraphs); - //} - // public boolean containsAllFilterKeyValuePairs() {} - // public boolean containsAllTriples() {} - // // CONTENT PARSING // - // parses the query to extract graphs, filters and triples + /** Parses the query to extract graphs, filters and triples. + * This does not work for INSERT queries (all update queries) + * + * @param queryString + */ private ParsedQueryContent parseQueryContent(String queryString) { List graphs = new LinkedList<>(); List filters = new LinkedList<>();