Makes testsuite parsing more robust

- avoids stack overflow if there are a lot of empty tests
- allows blank node test ids
- runs tests in the same order they are defined
pull/171/head
Tpt 3 years ago
parent 7764f41d37
commit 0ba0e4e399
  1. 4
      testsuite/oxigraph-tests/sparql/manifest.ttl
  2. 85
      testsuite/src/manifest.rs

@ -22,10 +22,10 @@
qt:data <describe_input.ttl> ] ;
mf:result <describe_output.ttl> .
:describe rdf:type mf:QueryEvaluationTest ;
:describe_where rdf:type mf:QueryEvaluationTest ;
mf:name "Simple DESCRIBE request" ;
mf:action
[ qt:query <describe.rq> ;
[ qt:query <describe_where.rq> ;
qt:data <describe_input.ttl> ] ;
mf:result <describe_output.ttl> .

@ -3,6 +3,7 @@ use crate::vocab::*;
use anyhow::{anyhow, Result};
use oxigraph::model::vocab::*;
use oxigraph::model::*;
use std::collections::VecDeque;
use std::fmt;
pub struct Test {
@ -50,15 +51,15 @@ impl fmt::Display for Test {
pub struct TestManifest {
graph: Graph,
tests_to_do: Vec<Term>,
manifests_to_do: Vec<String>,
tests_to_do: VecDeque<Term>,
manifests_to_do: VecDeque<String>,
}
impl TestManifest {
pub fn new<S: ToString>(manifest_urls: impl IntoIterator<Item = S>) -> Self {
Self {
graph: Graph::new(),
tests_to_do: Vec::new(),
tests_to_do: VecDeque::new(),
manifests_to_do: manifest_urls
.into_iter()
.map(|url| url.to_string())
@ -71,15 +72,19 @@ impl Iterator for TestManifest {
type Item = Result<Test>;
fn next(&mut self) -> Option<Result<Test>> {
match self.tests_to_do.pop() {
Some(Term::NamedNode(test_node)) => {
let kind = match self
.graph
.object_for_subject_predicate(&test_node, rdf::TYPE)
{
Some(TermRef::NamedNode(c)) => c.into_owned(),
_ => return self.next(), //We ignore the test
};
loop {
return match self.tests_to_do.pop_front().map(|term| match term {
Term::NamedNode(n) => Ok(n),
Term::BlankNode(n) => Ok(NamedNode::new(format!(
"http://oxigraph.org/.well-known/genid/{}",
n.as_str()
))?),
_ => Err(anyhow!("Invalid test identifier. Got {}", term)),
}) {
Some(Ok(test_node)) => {
if self.graph.triples_for_subject(&test_node).next().is_none() {
continue; // This test does not exists
}
let name = match self
.graph
.object_for_subject_predicate(&test_node, mf::NAME)
@ -87,6 +92,19 @@ impl Iterator for TestManifest {
Some(TermRef::Literal(c)) => Some(c.value().to_string()),
_ => None,
};
let kind = match self
.graph
.object_for_subject_predicate(&test_node, rdf::TYPE)
{
Some(TermRef::NamedNode(c)) => c.into_owned(),
_ => {
return Some(Err(anyhow!(
"The test {} named {} has no rdf:type",
test_node,
name.as_deref().unwrap_or("")
)))
}
};
let comment = match self
.graph
.object_for_subject_predicate(&test_node, rdfs::COMMENT)
@ -107,11 +125,13 @@ impl Iterator for TestManifest {
vec![],
),
Some(TermRef::BlankNode(n)) => {
let query = match self.graph.object_for_subject_predicate(n, qt::QUERY) {
let query = match self.graph.object_for_subject_predicate(n, qt::QUERY)
{
Some(TermRef::NamedNode(q)) => Some(q.as_str().to_owned()),
_ => None,
};
let update = match self.graph.object_for_subject_predicate(n, ut::REQUEST) {
let update =
match self.graph.object_for_subject_predicate(n, ut::REQUEST) {
Some(TermRef::NamedNode(q)) => Some(q.as_str().to_owned()),
_ => None,
};
@ -144,7 +164,10 @@ impl Iterator for TestManifest {
graph.as_str().to_owned(),
))
} else {
Some((graph.into_owned(), graph.as_str().to_owned()))
Some((
graph.into_owned(),
graph.as_str().to_owned(),
))
}
} else {
None
@ -169,7 +192,10 @@ impl Iterator for TestManifest {
self.graph.object_for_subject_predicate(g, qt::ENDPOINT),
self.graph.object_for_subject_predicate(g, qt::DATA),
) {
Some((endpoint.as_str().to_owned(), data.as_str().to_owned()))
Some((
endpoint.as_str().to_owned(),
data.as_str().to_owned(),
))
} else {
None
}
@ -214,7 +240,10 @@ impl Iterator for TestManifest {
graph.as_str().to_owned(),
))
} else {
Some((graph.into_owned(), graph.as_str().to_owned()))
Some((
graph.into_owned(),
graph.as_str().to_owned(),
))
}
} else {
None
@ -242,9 +271,9 @@ impl Iterator for TestManifest {
result_graph_data,
}))
}
Some(_) => self.next(),
Some(Err(error)) => Some(Err(error)),
None => {
match self.manifests_to_do.pop() {
match self.manifests_to_do.pop_front() {
Some(url) => {
self.graph.clear();
if let Err(error) = load_to_graph(&url, &mut self.graph) {
@ -261,12 +290,11 @@ impl Iterator for TestManifest {
{
Some(TermRef::BlankNode(list)) => {
self.manifests_to_do.extend(
RdfListIterator::iter(&self.graph, list.into()).filter_map(
|m| match m {
RdfListIterator::iter(&self.graph, list.into())
.filter_map(|m| match m {
Term::NamedNode(nm) => Some(nm.into_string()),
_ => None,
},
),
}),
);
}
Some(_) => return Some(Err(anyhow!("invalid tests list"))),
@ -279,8 +307,10 @@ impl Iterator for TestManifest {
.object_for_subject_predicate(manifest, mf::ENTRIES)
{
Some(TermRef::BlankNode(list)) => {
self.tests_to_do
.extend(RdfListIterator::iter(&self.graph, list.into()));
self.tests_to_do.extend(RdfListIterator::iter(
&self.graph,
list.into(),
));
}
Some(term) => {
return Some(Err(anyhow!(
@ -291,11 +321,12 @@ impl Iterator for TestManifest {
None => (),
}
}
continue;
}
None => return None,
None => None,
}
self.next()
}
};
}
}
}

Loading…
Cancel
Save