Better validation of test manifests

pull/289/head
Tpt 2 years ago committed by Thomas Tanon
parent 579c876f98
commit 841c9a2066
  1. 2
      testsuite/oxigraph-tests/sparql-results/manifest.ttl
  2. 2
      testsuite/rdf-tests
  3. 480
      testsuite/src/manifest.rs

@ -24,7 +24,7 @@
mf:name "Duplicated variables are not allowed" ; mf:name "Duplicated variables are not allowed" ;
mf:action <duplicated_variables.srx> . mf:action <duplicated_variables.srx> .
:results_xml_duplicated_variables rdf:type ox:NegativeTsvResultsSyntaxTest ; :results_tsv_duplicated_variables rdf:type ox:NegativeTsvResultsSyntaxTest ;
mf:name "Duplicated variables are not allowed" ; mf:name "Duplicated variables are not allowed" ;
mf:action <duplicated_variables.tsv> . mf:action <duplicated_variables.tsv> .

@ -1 +1 @@
Subproject commit 43b0eb9078f144c0d1c36f2c751b81922030eb1a Subproject commit d2cc355bf601d8574116f3ee76ca570925f35ac3

@ -73,261 +73,253 @@ impl Iterator for TestManifest {
fn next(&mut self) -> Option<Result<Test>> { fn next(&mut self) -> Option<Result<Test>> {
loop { loop {
return match self.tests_to_do.pop_front().map(|term| match term { if let Some(next) = self.next_test() {
Term::NamedNode(n) => Ok(n), return Some(next);
Term::BlankNode(n) => Ok(NamedNode::new(format!( }
"http://oxigraph.org/.well-known/genid/{}", if let Err(e) = self.load_next_manifest()? {
n.as_str() return Some(Err(e));
))?), }
_ => 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 impl TestManifest {
} fn next_test(&mut self) -> Option<Result<Test>> {
let name = match self let test_node = self.tests_to_do.pop_front()?;
.graph let test_node = match test_node {
.object_for_subject_predicate(&test_node, mf::NAME) Term::NamedNode(n) => n,
{ _ => {
Some(TermRef::Literal(c)) => Some(c.value().to_string()), return Some(Err(anyhow!("Invalid test identifier. Got {}", test_node)));
_ => None, }
}; };
let kind = match self
.graph let name = match self
.object_for_subject_predicate(&test_node, rdf::TYPE) .graph
{ .object_for_subject_predicate(&test_node, mf::NAME)
Some(TermRef::NamedNode(c)) => c.into_owned(), {
_ => { Some(TermRef::Literal(c)) => Some(c.value().to_string()),
return Some(Err(anyhow!( _ => None,
"The test {} named {} has no rdf:type", };
test_node, let kind = match self
name.as_deref().unwrap_or("") .graph
))) .object_for_subject_predicate(&test_node, rdf::TYPE)
} {
}; Some(TermRef::NamedNode(c)) => c.into_owned(),
let comment = match self _ => {
.graph return if test_node
.object_for_subject_predicate(&test_node, rdfs::COMMENT) .as_str()
{ .starts_with("http://www.w3.org/2001/sw/DataAccess/tests/data-r2")
Some(TermRef::Literal(c)) => Some(c.value().to_string()), {
_ => None, self.next_test() //TODO: hack to ignore invalid tests: https://github.com/w3c/rdf-tests/pull/82
}; } else {
let (action, query, update, data, graph_data, service_data) = match self Some(Err(anyhow!(
.graph "The test {} named {} has no rdf:type",
.object_for_subject_predicate(&test_node, mf::ACTION) test_node,
{ name.as_deref().unwrap_or("")
Some(TermRef::NamedNode(n)) => ( )))
Some(n.as_str().to_owned()), };
None, }
None, };
None, let comment = match self
vec![], .graph
vec![], .object_for_subject_predicate(&test_node, rdfs::COMMENT)
), {
Some(TermRef::BlankNode(n)) => { Some(TermRef::Literal(c)) => Some(c.value().to_string()),
let query = match self.graph.object_for_subject_predicate(n, qt::QUERY) _ => None,
{ };
Some(TermRef::NamedNode(q)) => Some(q.as_str().to_owned()), let (action, query, update, data, graph_data, service_data) = match self
_ => None, .graph
}; .object_for_subject_predicate(&test_node, mf::ACTION)
let update = {
match self.graph.object_for_subject_predicate(n, ut::REQUEST) { Some(TermRef::NamedNode(n)) => (
Some(TermRef::NamedNode(q)) => Some(q.as_str().to_owned()), Some(n.as_str().to_owned()),
_ => None, None,
}; None,
let data = match self None,
.graph vec![],
.object_for_subject_predicate(n, qt::DATA) vec![],
.or_else(|| self.graph.object_for_subject_predicate(n, ut::DATA)) ),
{ Some(TermRef::BlankNode(n)) => {
Some(TermRef::NamedNode(q)) => Some(q.as_str().to_owned()), let query = match self.graph.object_for_subject_predicate(n, qt::QUERY) {
_ => None, Some(TermRef::NamedNode(q)) => Some(q.as_str().to_owned()),
}; _ => None,
let graph_data = self };
.graph let update = match self.graph.object_for_subject_predicate(n, ut::REQUEST) {
.objects_for_subject_predicate(n, qt::GRAPH_DATA) Some(TermRef::NamedNode(q)) => Some(q.as_str().to_owned()),
.chain(self.graph.objects_for_subject_predicate(n, ut::GRAPH_DATA)) _ => None,
.filter_map(|g| match g { };
TermRef::NamedNode(q) => { let data = match self
Some((q.into_owned(), q.as_str().to_owned())) .graph
} .object_for_subject_predicate(n, qt::DATA)
TermRef::BlankNode(node) => { .or_else(|| self.graph.object_for_subject_predicate(n, ut::DATA))
if let Some(TermRef::NamedNode(graph)) = {
self.graph.object_for_subject_predicate(node, ut::GRAPH) Some(TermRef::NamedNode(q)) => Some(q.as_str().to_owned()),
{ _ => None,
if let Some(TermRef::Literal(name)) = self };
.graph let graph_data = self
.object_for_subject_predicate(node, rdfs::LABEL) .graph
{ .objects_for_subject_predicate(n, qt::GRAPH_DATA)
Some(( .chain(self.graph.objects_for_subject_predicate(n, ut::GRAPH_DATA))
NamedNode::new(name.value()).unwrap(), .filter_map(|g| match g {
graph.as_str().to_owned(), TermRef::NamedNode(q) => Some((q.into_owned(), q.as_str().to_owned())),
)) TermRef::BlankNode(node) => {
} else { if let Some(TermRef::NamedNode(graph)) =
Some(( self.graph.object_for_subject_predicate(node, ut::GRAPH)
graph.into_owned(),
graph.as_str().to_owned(),
))
}
} else {
None
}
}
_ => None,
})
.collect();
let service_data = self
.graph
.objects_for_subject_predicate(n, qt::SERVICE_DATA)
.filter_map(|g| match g {
TermRef::NamedNode(g) => Some(g.into()),
TermRef::BlankNode(g) => Some(g.into()),
_ => None,
})
.filter_map(|g: SubjectRef<'_>| {
if let (
Some(TermRef::NamedNode(endpoint)),
Some(TermRef::NamedNode(data)),
) = (
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(),
))
} else {
None
}
})
.collect();
(None, query, update, data, graph_data, service_data)
}
Some(_) => return Some(Err(anyhow!("invalid action"))),
None => {
return Some(Err(anyhow!("action not found for test {}", test_node)));
}
};
let (result, result_graph_data) = match self
.graph
.object_for_subject_predicate(&test_node, mf::RESULT)
{
Some(TermRef::NamedNode(n)) => (Some(n.as_str().to_owned()), Vec::new()),
Some(TermRef::BlankNode(n)) => (
if let Some(TermRef::NamedNode(result)) =
self.graph.object_for_subject_predicate(n, ut::DATA)
{ {
Some(result.as_str().to_owned()) if let Some(TermRef::Literal(name)) =
self.graph.object_for_subject_predicate(node, rdfs::LABEL)
{
Some((
NamedNode::new(name.value()).unwrap(),
graph.as_str().to_owned(),
))
} else {
Some((graph.into_owned(), graph.as_str().to_owned()))
}
} else { } else {
None None
},
self.graph
.objects_for_subject_predicate(n, ut::GRAPH_DATA)
.filter_map(|g| match g {
TermRef::NamedNode(q) => {
Some((q.into_owned(), q.as_str().to_owned()))
}
TermRef::BlankNode(node) => {
if let Some(TermRef::NamedNode(graph)) =
self.graph.object_for_subject_predicate(node, ut::GRAPH)
{
if let Some(TermRef::Literal(name)) = self
.graph
.object_for_subject_predicate(node, rdfs::LABEL)
{
Some((
NamedNode::new(name.value()).unwrap(),
graph.as_str().to_owned(),
))
} else {
Some((
graph.into_owned(),
graph.as_str().to_owned(),
))
}
} else {
None
}
}
_ => None,
})
.collect(),
),
Some(_) => return Some(Err(anyhow!("invalid result"))),
None => (None, Vec::new()),
};
Some(Ok(Test {
id: test_node,
kind,
name,
comment,
action,
query,
update,
data,
graph_data,
service_data,
result,
result_graph_data,
}))
}
Some(Err(error)) => Some(Err(error)),
None => {
match self.manifests_to_do.pop_front() {
Some(url) => {
self.graph.clear();
if let Err(error) = load_to_graph(&url, &mut self.graph) {
return Some(Err(error));
} }
}
for manifest in self _ => None,
.graph })
.subjects_for_predicate_object(rdf::TYPE, mf::MANIFEST) .collect();
let service_data = self
.graph
.objects_for_subject_predicate(n, qt::SERVICE_DATA)
.filter_map(|g| match g {
TermRef::NamedNode(g) => Some(g.into()),
TermRef::BlankNode(g) => Some(g.into()),
_ => None,
})
.filter_map(|g: SubjectRef<'_>| {
if let (
Some(TermRef::NamedNode(endpoint)),
Some(TermRef::NamedNode(data)),
) = (
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()))
} else {
None
}
})
.collect();
(None, query, update, data, graph_data, service_data)
}
Some(_) => return Some(Err(anyhow!("invalid action"))),
None => {
return Some(Err(anyhow!("action not found for test {}", test_node)));
}
};
let (result, result_graph_data) = match self
.graph
.object_for_subject_predicate(&test_node, mf::RESULT)
{
Some(TermRef::NamedNode(n)) => (Some(n.as_str().to_owned()), Vec::new()),
Some(TermRef::BlankNode(n)) => (
if let Some(TermRef::NamedNode(result)) =
self.graph.object_for_subject_predicate(n, ut::DATA)
{
Some(result.as_str().to_owned())
} else {
None
},
self.graph
.objects_for_subject_predicate(n, ut::GRAPH_DATA)
.filter_map(|g| match g {
TermRef::NamedNode(q) => Some((q.into_owned(), q.as_str().to_owned())),
TermRef::BlankNode(node) => {
if let Some(TermRef::NamedNode(graph)) =
self.graph.object_for_subject_predicate(node, ut::GRAPH)
{ {
match self if let Some(TermRef::Literal(name)) =
.graph self.graph.object_for_subject_predicate(node, rdfs::LABEL)
.object_for_subject_predicate(manifest, mf::INCLUDE)
{
Some(TermRef::BlankNode(list)) => {
self.manifests_to_do.extend(
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"))),
None => (),
}
// New tests
match self
.graph
.object_for_subject_predicate(manifest, mf::ENTRIES)
{ {
Some(TermRef::BlankNode(list)) => { Some((
self.tests_to_do.extend(RdfListIterator::iter( NamedNode::new(name.value()).unwrap(),
&self.graph, graph.as_str().to_owned(),
list.into(), ))
)); } else {
} Some((graph.into_owned(), graph.as_str().to_owned()))
Some(term) => {
return Some(Err(anyhow!(
"Invalid tests list. Got term {}",
term
)));
}
None => (),
} }
} else {
None
} }
continue;
} }
None => None, _ => None,
} })
.collect(),
),
Some(_) => return Some(Err(anyhow!("invalid result"))),
None => (None, Vec::new()),
};
Some(Ok(Test {
id: test_node,
kind,
name,
comment,
action,
query,
update,
data,
graph_data,
service_data,
result,
result_graph_data,
}))
}
fn load_next_manifest(&mut self) -> Option<Result<()>> {
let url = self.manifests_to_do.pop_front()?;
self.graph.clear();
if let Err(error) = load_to_graph(&url, &mut self.graph) {
return Some(Err(error));
}
let manifests = self
.graph
.subjects_for_predicate_object(rdf::TYPE, mf::MANIFEST)
.collect::<Vec<_>>();
if manifests.len() != 1 {
return Some(Err(anyhow!(
"The file {} should contain a single manifest",
url
)));
}
for manifest in manifests {
match self
.graph
.object_for_subject_predicate(manifest, mf::INCLUDE)
{
Some(TermRef::BlankNode(list)) => {
self.manifests_to_do.extend(
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"))),
None => (),
}
// New tests
match self
.graph
.object_for_subject_predicate(manifest, mf::ENTRIES)
{
Some(TermRef::BlankNode(list)) => {
self.tests_to_do
.extend(RdfListIterator::iter(&self.graph, list.into()));
}
Some(term) => {
return Some(Err(anyhow!("Invalid tests list. Got term {}", term)));
} }
}; None => (),
}
} }
Some(Ok(()))
} }
} }

Loading…
Cancel
Save