diff --git a/tests/examples/Makefile b/tests/examples/Makefile index a2e11727..93b8a306 100644 --- a/tests/examples/Makefile +++ b/tests/examples/Makefile @@ -22,14 +22,31 @@ all: \ action_inheritance_XFAIL_validation.ttl \ action_result_PASS_validation.ttl \ location_PASS_validation.ttl \ - location_XFAIL_validation.ttl + location_XFAIL_validation.ttl \ + relationship_PASS_validation.ttl \ + relationship_PASS_via_rdflib_validation_after_translation.ttl \ + relationship_PASS_via_rdf_toolkit_validation_after_translation.ttl \ + relationship_XFAIL_validation.ttl + +.PHONY: \ + check-context .PRECIOUS: \ - %_PASS_validation.ttl \ - %_XFAIL_validation.ttl + %_validation.ttl \ + relationship_PASS_via_rdflib.ttl \ + relationship_PASS_via_rdf_toolkit.ttl -%_PASS_validation.ttl: \ - %_PASS.json \ +# NOTE - this recipe makes an allowance for a certain failure type +# reported by pyshacl. Pyshacl will exit status 1 in the case where +# "DataGraph is Non-Conformant". This XFAIL test is intenced to +# generate a non-conformance result, and feed that result forward to +# pytest. Hence, the Make recipe allows for an exit status of 0 or 1. +# (0 would cause an expected failure later in pytest.) +# Note that should another issue cause an exit status of 1, pytest will +# fail because the result validation-graph file would not have expected +# characteristics. +%_validation.ttl: \ + %.json \ $(tests_srcdir)/.venv.done.log \ $(tests_srcdir)/uco_monolithic.ttl source $(tests_srcdir)/venv/bin/activate \ @@ -41,48 +58,95 @@ all: \ --ont-graph $(tests_srcdir)/uco_monolithic.ttl \ --shacl $(tests_srcdir)/uco_monolithic.ttl \ --shacl-file-format turtle \ - --output _$@ \ + --output __$@ \ $< \ - || (cat _$@ ; exit 1) + ; rc=$$? ; test 0 -eq $$rc -o 1 -eq $$rc + java -jar $(top_srcdir)/lib/rdf-toolkit.jar \ + --infer-base-iri \ + --inline-blank-nodes \ + --source __$@ \ + --source-format turtle \ + --target _$@ \ + --target-format turtle + rm __$@ mv _$@ $@ -# NOTE - this recipe makes an allowance for a certain failure type -# reported by pyshacl. Pyshacl will exit status 1 in the case where -# "DataGraph is Non-Conformant". This XFAIL test is intenced to -# generate a non-conformance result, and feed that result forward to -# pytest. Hence, the Make recipe allows for an exit status of 0 or 1. -# (0 would cause an expected failure later in pytest.) -# Note that should another issue cause an exit status of 1, pytest will -# fail because the result validation-graph file would not have expected -# characteristics. -%_XFAIL_validation.ttl: \ - %_XFAIL.json \ +%_validation_after_translation.ttl: \ + %.ttl \ $(tests_srcdir)/.venv.done.log \ $(tests_srcdir)/uco_monolithic.ttl source $(tests_srcdir)/venv/bin/activate \ && pyshacl \ - --data-file-format json-ld \ + --data-file-format turtle \ --format turtle \ --inference none \ --ont-file-format turtle \ --ont-graph $(tests_srcdir)/uco_monolithic.ttl \ --shacl $(tests_srcdir)/uco_monolithic.ttl \ --shacl-file-format turtle \ - --output _$@ \ + --output __$@ \ $< \ ; rc=$$? ; test 0 -eq $$rc -o 1 -eq $$rc + java -jar $(top_srcdir)/lib/rdf-toolkit.jar \ + --infer-base-iri \ + --inline-blank-nodes \ + --source __$@ \ + --source-format turtle \ + --target _$@ \ + --target-format turtle + rm __$@ mv _$@ $@ check: \ action_inheritance_PASS_validation.ttl \ action_inheritance_XFAIL_validation.ttl \ action_result_PASS_validation.ttl \ + check-context \ location_PASS_validation.ttl \ - location_XFAIL_validation.ttl + location_XFAIL_validation.ttl \ + relationship_PASS_validation.ttl \ + relationship_PASS_via_rdflib_validation_after_translation.ttl \ + relationship_PASS_via_rdf_toolkit_validation_after_translation.ttl \ + relationship_XFAIL_validation.ttl source $(tests_srcdir)/venv/bin/activate \ && pytest \ --log-level=DEBUG +# These Turtle renders of the JSON file are for confirming data characteristics are preserved when consumed by multiple RDF applications. +check-context: \ + relationship_PASS_via_rdflib.ttl \ + relationship_PASS_via_rdf_toolkit.ttl + diff $^ + clean: @rm -f \ - *_validation.ttl + *_validation*.ttl + +relationship_PASS_via_rdf_toolkit.ttl: \ + relationship_PASS.json + java -jar $(top_srcdir)/lib/rdf-toolkit.jar \ + --infer-base-iri \ + --inline-blank-nodes \ + --source $< \ + --source-format json-ld \ + --target _$@ \ + --target-format turtle + mv _$@ $@ + +relationship_PASS_via_rdflib.ttl: \ + relationship_PASS.json \ + $(tests_srcdir)/.venv.done.log \ + $(tests_srcdir)/src/glom_graph.py + source $(tests_srcdir)/venv/bin/activate \ + && python3 $(tests_srcdir)/src/glom_graph.py \ + __$@ \ + $< + java -jar $(top_srcdir)/lib/rdf-toolkit.jar \ + --infer-base-iri \ + --inline-blank-nodes \ + --source __$@ \ + --source-format turtle \ + --target _$@ \ + --target-format turtle + rm __$@ + mv _$@ $@ diff --git a/tests/examples/action_inheritance_PASS_validation.ttl b/tests/examples/action_inheritance_PASS_validation.ttl index 9b8084b8..33496ff0 100644 --- a/tests/examples/action_inheritance_PASS_validation.ttl +++ b/tests/examples/action_inheritance_PASS_validation.ttl @@ -1,6 +1,11 @@ +@prefix owl: . +@prefix rdf: . +@prefix rdfs: . @prefix sh: . @prefix xsd: . -[] a sh:ValidationReport ; - sh:conforms true . +[] + a sh:ValidationReport ; + sh:conforms "true"^^xsd:boolean ; + . diff --git a/tests/examples/action_inheritance_XFAIL_validation.ttl b/tests/examples/action_inheritance_XFAIL_validation.ttl index 227ace7a..1f338fbf 100644 --- a/tests/examples/action_inheritance_XFAIL_validation.ttl +++ b/tests/examples/action_inheritance_XFAIL_validation.ttl @@ -1,123 +1,236 @@ @prefix action: . +@prefix owl: . +@prefix rdf: . +@prefix rdfs: . @prefix sh: . @prefix vocabulary: . @prefix xsd: . -[] a sh:ValidationReport ; - sh:conforms false ; - sh:result [ a sh:ValidationResult ; - sh:focusNode _:N970196d81ff64097bd30c4f202d9e292 ; - sh:resultMessage "Value is not of Node Kind sh:BlankNodeOrIRI" ; - sh:resultPath action:action ; - sh:resultSeverity sh:Violation ; - sh:sourceConstraintComponent sh:NodeKindConstraintComponent ; - sh:sourceShape _:n2de63136fe57446790f1cbc9cd83ac14b30 ; - sh:value "kb:action3" ], - [ a sh:ValidationResult ; - sh:focusNode _:N970196d81ff64097bd30c4f202d9e292 ; - sh:resultMessage "Value does not have class action:Action" ; - sh:resultPath action:action ; - sh:resultSeverity sh:Violation ; - sh:sourceConstraintComponent sh:ClassConstraintComponent ; - sh:sourceShape _:n2de63136fe57446790f1cbc9cd83ac14b30 ; - sh:value "kb:action1" ], - [ a sh:ValidationResult ; - sh:focusNode _:N970196d81ff64097bd30c4f202d9e292 ; - sh:resultMessage "Value does not have class action:Action" ; - sh:resultPath action:action ; - sh:resultSeverity sh:Violation ; - sh:sourceConstraintComponent sh:ClassConstraintComponent ; - sh:sourceShape _:n2de63136fe57446790f1cbc9cd83ac14b30 ; - sh:value "kb:action3" ], - [ a sh:ValidationResult ; - sh:focusNode ; - sh:resultMessage "Value is not Literal with datatype vocabulary:ActionStatusTypeVocab" ; - sh:resultPath action:actionStatus ; - sh:resultSeverity sh:Violation ; - sh:sourceConstraintComponent sh:DatatypeConstraintComponent ; - sh:sourceShape _:n2de63136fe57446790f1cbc9cd83ac14b6 ; - sh:value "Pending" ], - [ a sh:ValidationResult ; - sh:focusNode ; - sh:resultMessage "More than 0 values on kb:action-lifecycle1->action:actionStatus" ; - sh:resultPath action:actionStatus ; - sh:resultSeverity sh:Violation ; - sh:sourceConstraintComponent sh:MaxCountConstraintComponent ; - sh:sourceShape _:n2de63136fe57446790f1cbc9cd83ac14b22 ], - [ a sh:ValidationResult ; - sh:focusNode _:N970196d81ff64097bd30c4f202d9e292 ; - sh:resultMessage "Value is not of Node Kind sh:BlankNodeOrIRI" ; - sh:resultPath action:action ; - sh:resultSeverity sh:Violation ; - sh:sourceConstraintComponent sh:NodeKindConstraintComponent ; - sh:sourceShape _:n2de63136fe57446790f1cbc9cd83ac14b30 ; - sh:value "kb:action2" ], - [ a sh:ValidationResult ; - sh:focusNode ; - sh:resultMessage "Value is not Literal with datatype vocabulary:ActionStatusTypeVocab" ; - sh:resultPath action:actionStatus ; - sh:resultSeverity sh:Violation ; - sh:sourceConstraintComponent sh:DatatypeConstraintComponent ; - sh:sourceShape _:n2de63136fe57446790f1cbc9cd83ac14b22 ; - sh:value "Pending" ], - [ a sh:ValidationResult ; - sh:focusNode _:N970196d81ff64097bd30c4f202d9e292 ; - sh:resultMessage "Value is not of Node Kind sh:BlankNodeOrIRI" ; - sh:resultPath action:action ; - sh:resultSeverity sh:Violation ; - sh:sourceConstraintComponent sh:NodeKindConstraintComponent ; - sh:sourceShape _:n2de63136fe57446790f1cbc9cd83ac14b30 ; - sh:value "kb:action1" ], - [ a sh:ValidationResult ; - sh:focusNode ; - sh:resultMessage "Value is not Literal with datatype vocabulary:ActionStatusTypeVocab" ; - sh:resultPath action:actionStatus ; - sh:resultSeverity sh:Violation ; - sh:sourceConstraintComponent sh:DatatypeConstraintComponent ; - sh:sourceShape _:n2de63136fe57446790f1cbc9cd83ac14b6 ; - sh:value "Pending" ], - [ a sh:ValidationResult ; - sh:focusNode ; - sh:resultMessage "Value is not Literal with datatype vocabulary:ActionStatusTypeVocab" ; - sh:resultPath action:actionStatus ; - sh:resultSeverity sh:Violation ; - sh:sourceConstraintComponent sh:DatatypeConstraintComponent ; - sh:sourceShape _:n2de63136fe57446790f1cbc9cd83ac14b6 ; - sh:value "Pending" ], - [ a sh:ValidationResult ; - sh:focusNode ; - sh:resultMessage "Value is not Literal with datatype vocabulary:ActionStatusTypeVocab" ; - sh:resultPath action:actionStatus ; - sh:resultSeverity sh:Violation ; - sh:sourceConstraintComponent sh:DatatypeConstraintComponent ; - sh:sourceShape _:n2de63136fe57446790f1cbc9cd83ac14b6 ; - sh:value "Pending" ], - [ a sh:ValidationResult ; - sh:focusNode _:N970196d81ff64097bd30c4f202d9e292 ; - sh:resultMessage "Value does not have class action:Action" ; - sh:resultPath action:action ; - sh:resultSeverity sh:Violation ; - sh:sourceConstraintComponent sh:ClassConstraintComponent ; - sh:sourceShape _:n2de63136fe57446790f1cbc9cd83ac14b30 ; - sh:value "kb:action2" ] . - -_:n2de63136fe57446790f1cbc9cd83ac14b22 sh:datatype vocabulary:ActionStatusTypeVocab ; - sh:maxCount 0 ; - sh:nodeKind sh:Literal ; - sh:path action:actionStatus . - -_:n2de63136fe57446790f1cbc9cd83ac14b6 sh:datatype vocabulary:ActionStatusTypeVocab ; - sh:maxCount 1 ; - sh:nodeKind sh:Literal ; - sh:path action:actionStatus . - -_:N970196d81ff64097bd30c4f202d9e292 a action:ArrayOfAction ; - action:action "kb:action1", - "kb:action2", - "kb:action3" . - -_:n2de63136fe57446790f1cbc9cd83ac14b30 sh:class action:Action ; - sh:minCount 1 ; - sh:nodeKind sh:BlankNodeOrIRI ; - sh:path action:action . +[] + a sh:ValidationReport ; + sh:conforms "false"^^xsd:boolean ; + sh:result + [ + a sh:ValidationResult ; + sh:focusNode ; + sh:resultMessage "More than 0 values on kb:action-lifecycle1->action:actionStatus" ; + sh:resultPath action:actionStatus ; + sh:resultSeverity sh:Violation ; + sh:sourceConstraintComponent sh:MaxCountConstraintComponent ; + sh:sourceShape [ + sh:datatype vocabulary:ActionStatusTypeVocab ; + sh:maxCount "0"^^xsd:integer ; + sh:nodeKind sh:Literal ; + sh:path action:actionStatus ; + ] ; + ] , + [ + a sh:ValidationResult ; + sh:focusNode ; + sh:resultMessage "Value is not Literal with datatype vocabulary:ActionStatusTypeVocab" ; + sh:resultPath action:actionStatus ; + sh:resultSeverity sh:Violation ; + sh:sourceConstraintComponent sh:DatatypeConstraintComponent ; + sh:sourceShape [ + sh:datatype vocabulary:ActionStatusTypeVocab ; + sh:maxCount "0"^^xsd:integer ; + sh:nodeKind sh:Literal ; + sh:path action:actionStatus ; + ] ; + sh:value "Pending" ; + ] , + [ + a sh:ValidationResult ; + sh:focusNode ; + sh:resultMessage "Value is not Literal with datatype vocabulary:ActionStatusTypeVocab" ; + sh:resultPath action:actionStatus ; + sh:resultSeverity sh:Violation ; + sh:sourceConstraintComponent sh:DatatypeConstraintComponent ; + sh:sourceShape [ + sh:datatype vocabulary:ActionStatusTypeVocab ; + sh:maxCount "1"^^xsd:integer ; + sh:nodeKind sh:Literal ; + sh:path action:actionStatus ; + ] ; + sh:value "Pending" ; + ] , + [ + a sh:ValidationResult ; + sh:focusNode ; + sh:resultMessage "Value is not Literal with datatype vocabulary:ActionStatusTypeVocab" ; + sh:resultPath action:actionStatus ; + sh:resultSeverity sh:Violation ; + sh:sourceConstraintComponent sh:DatatypeConstraintComponent ; + sh:sourceShape [ + sh:datatype vocabulary:ActionStatusTypeVocab ; + sh:maxCount "1"^^xsd:integer ; + sh:nodeKind sh:Literal ; + sh:path action:actionStatus ; + ] ; + sh:value "Pending" ; + ] , + [ + a sh:ValidationResult ; + sh:focusNode ; + sh:resultMessage "Value is not Literal with datatype vocabulary:ActionStatusTypeVocab" ; + sh:resultPath action:actionStatus ; + sh:resultSeverity sh:Violation ; + sh:sourceConstraintComponent sh:DatatypeConstraintComponent ; + sh:sourceShape [ + sh:datatype vocabulary:ActionStatusTypeVocab ; + sh:maxCount "1"^^xsd:integer ; + sh:nodeKind sh:Literal ; + sh:path action:actionStatus ; + ] ; + sh:value "Pending" ; + ] , + [ + a sh:ValidationResult ; + sh:focusNode ; + sh:resultMessage "Value is not Literal with datatype vocabulary:ActionStatusTypeVocab" ; + sh:resultPath action:actionStatus ; + sh:resultSeverity sh:Violation ; + sh:sourceConstraintComponent sh:DatatypeConstraintComponent ; + sh:sourceShape [ + sh:datatype vocabulary:ActionStatusTypeVocab ; + sh:maxCount "1"^^xsd:integer ; + sh:nodeKind sh:Literal ; + sh:path action:actionStatus ; + ] ; + sh:value "Pending" ; + ] , + [ + a sh:ValidationResult ; + sh:focusNode [ + a action:ArrayOfAction ; + action:action + "kb:action1" , + "kb:action2" , + "kb:action3" + ; + ] ; + sh:resultMessage "Value does not have class action:Action" ; + sh:resultPath action:action ; + sh:resultSeverity sh:Violation ; + sh:sourceConstraintComponent sh:ClassConstraintComponent ; + sh:sourceShape [ + sh:class action:Action ; + sh:minCount "1"^^xsd:integer ; + sh:nodeKind sh:BlankNodeOrIRI ; + sh:path action:action ; + ] ; + sh:value "kb:action1" ; + ] , + [ + a sh:ValidationResult ; + sh:focusNode [ + a action:ArrayOfAction ; + action:action + "kb:action1" , + "kb:action2" , + "kb:action3" + ; + ] ; + sh:resultMessage "Value does not have class action:Action" ; + sh:resultPath action:action ; + sh:resultSeverity sh:Violation ; + sh:sourceConstraintComponent sh:ClassConstraintComponent ; + sh:sourceShape [ + sh:class action:Action ; + sh:minCount "1"^^xsd:integer ; + sh:nodeKind sh:BlankNodeOrIRI ; + sh:path action:action ; + ] ; + sh:value "kb:action2" ; + ] , + [ + a sh:ValidationResult ; + sh:focusNode [ + a action:ArrayOfAction ; + action:action + "kb:action1" , + "kb:action2" , + "kb:action3" + ; + ] ; + sh:resultMessage "Value does not have class action:Action" ; + sh:resultPath action:action ; + sh:resultSeverity sh:Violation ; + sh:sourceConstraintComponent sh:ClassConstraintComponent ; + sh:sourceShape [ + sh:class action:Action ; + sh:minCount "1"^^xsd:integer ; + sh:nodeKind sh:BlankNodeOrIRI ; + sh:path action:action ; + ] ; + sh:value "kb:action3" ; + ] , + [ + a sh:ValidationResult ; + sh:focusNode [ + a action:ArrayOfAction ; + action:action + "kb:action1" , + "kb:action2" , + "kb:action3" + ; + ] ; + sh:resultMessage "Value is not of Node Kind sh:BlankNodeOrIRI" ; + sh:resultPath action:action ; + sh:resultSeverity sh:Violation ; + sh:sourceConstraintComponent sh:NodeKindConstraintComponent ; + sh:sourceShape [ + sh:class action:Action ; + sh:minCount "1"^^xsd:integer ; + sh:nodeKind sh:BlankNodeOrIRI ; + sh:path action:action ; + ] ; + sh:value "kb:action1" ; + ] , + [ + a sh:ValidationResult ; + sh:focusNode [ + a action:ArrayOfAction ; + action:action + "kb:action1" , + "kb:action2" , + "kb:action3" + ; + ] ; + sh:resultMessage "Value is not of Node Kind sh:BlankNodeOrIRI" ; + sh:resultPath action:action ; + sh:resultSeverity sh:Violation ; + sh:sourceConstraintComponent sh:NodeKindConstraintComponent ; + sh:sourceShape [ + sh:class action:Action ; + sh:minCount "1"^^xsd:integer ; + sh:nodeKind sh:BlankNodeOrIRI ; + sh:path action:action ; + ] ; + sh:value "kb:action2" ; + ] , + [ + a sh:ValidationResult ; + sh:focusNode [ + a action:ArrayOfAction ; + action:action + "kb:action1" , + "kb:action2" , + "kb:action3" + ; + ] ; + sh:resultMessage "Value is not of Node Kind sh:BlankNodeOrIRI" ; + sh:resultPath action:action ; + sh:resultSeverity sh:Violation ; + sh:sourceConstraintComponent sh:NodeKindConstraintComponent ; + sh:sourceShape [ + sh:class action:Action ; + sh:minCount "1"^^xsd:integer ; + sh:nodeKind sh:BlankNodeOrIRI ; + sh:path action:action ; + ] ; + sh:value "kb:action3" ; + ] + ; + . diff --git a/tests/examples/action_result_PASS_validation.ttl b/tests/examples/action_result_PASS_validation.ttl index a2cbde14..33496ff0 100644 --- a/tests/examples/action_result_PASS_validation.ttl +++ b/tests/examples/action_result_PASS_validation.ttl @@ -1,26 +1,11 @@ -@prefix action: . -@prefix core: . +@prefix owl: . +@prefix rdf: . +@prefix rdfs: . @prefix sh: . @prefix xsd: . -[] a sh:ValidationReport ; - sh:conforms false ; - sh:result [ a sh:ValidationResult ; - sh:focusNode [ a action:ActionReferencesFacet ; - action:result , - , - , - , - , - , - , - ] ; - sh:resultMessage "Value does not have class core:UcoObject" ; - sh:resultPath action:result ; - sh:resultSeverity sh:Violation ; - sh:sourceConstraintComponent sh:ClassConstraintComponent ; - sh:sourceShape [ sh:class core:UcoObject ; - sh:nodeKind sh:BlankNodeOrIRI ; - sh:path action:result ] ; - sh:value ] . +[] + a sh:ValidationReport ; + sh:conforms "true"^^xsd:boolean ; + . diff --git a/tests/examples/location_PASS_validation.ttl b/tests/examples/location_PASS_validation.ttl index 9b8084b8..33496ff0 100644 --- a/tests/examples/location_PASS_validation.ttl +++ b/tests/examples/location_PASS_validation.ttl @@ -1,6 +1,11 @@ +@prefix owl: . +@prefix rdf: . +@prefix rdfs: . @prefix sh: . @prefix xsd: . -[] a sh:ValidationReport ; - sh:conforms true . +[] + a sh:ValidationReport ; + sh:conforms "true"^^xsd:boolean ; + . diff --git a/tests/examples/location_XFAIL_validation.ttl b/tests/examples/location_XFAIL_validation.ttl index e780d771..9be9d0b6 100644 --- a/tests/examples/location_XFAIL_validation.ttl +++ b/tests/examples/location_XFAIL_validation.ttl @@ -1,48 +1,73 @@ @prefix core: . @prefix location: . @prefix ns1: . +@prefix owl: . +@prefix rdf: . +@prefix rdfs: . @prefix sh: . @prefix xsd: . -[] a sh:ValidationReport ; - sh:conforms false ; - sh:result [ a sh:ValidationResult ; - sh:focusNode ; - sh:resultMessage "Value does not have class core:Facet" ; - sh:resultPath core:hasFacet ; - sh:resultSeverity sh:Violation ; - sh:sourceConstraintComponent sh:ClassConstraintComponent ; - sh:sourceShape _:n6057bf06e71546a1b8dbdbfa86ecb544b52 ; - sh:value [ a ns1:InternalLocationFacet ; - ns1:floor 3 ; - ns1:roomNumber "345" ] ], - [ a sh:ValidationResult ; - sh:focusNode ; - sh:resultMessage "Value does not have class core:Facet" ; - sh:resultPath core:hasFacet ; - sh:resultSeverity sh:Violation ; - sh:sourceConstraintComponent sh:ClassConstraintComponent ; - sh:sourceShape _:n6057bf06e71546a1b8dbdbfa86ecb544b52 ; - sh:value [ a location:LatLongCoordinates ; - location:latitude 48.860346 ; - location:longitude 2.331199 ] ], - [ a sh:ValidationResult ; - sh:focusNode [ a location:SimpleAddressFacet ; - location:locality "Seattle" ; - location:postalCode 98052 ; - location:region "WA" ; - location:street "20341 Whitworth Institute 405 N. Whitworth" ] ; - sh:resultMessage "Value is not Literal with datatype xsd:string" ; - sh:resultPath location:postalCode ; - sh:resultSeverity sh:Violation ; - sh:sourceConstraintComponent sh:DatatypeConstraintComponent ; - sh:sourceShape [ sh:datatype xsd:string ; - sh:maxCount 1 ; - sh:nodeKind sh:Literal ; - sh:path location:postalCode ] ; - sh:value 98052 ] . - -_:n6057bf06e71546a1b8dbdbfa86ecb544b52 sh:class core:Facet ; - sh:nodeKind sh:BlankNodeOrIRI ; - sh:path core:hasFacet . +[] + a sh:ValidationReport ; + sh:conforms "false"^^xsd:boolean ; + sh:result + [ + a sh:ValidationResult ; + sh:focusNode ; + sh:resultMessage "Value does not have class core:Facet" ; + sh:resultPath core:hasFacet ; + sh:resultSeverity sh:Violation ; + sh:sourceConstraintComponent sh:ClassConstraintComponent ; + sh:sourceShape [ + sh:class core:Facet ; + sh:nodeKind sh:BlankNodeOrIRI ; + sh:path core:hasFacet ; + ] ; + sh:value [ + a ns1:InternalLocationFacet ; + ns1:floor "3"^^xsd:integer ; + ns1:roomNumber "345" ; + ] ; + ] , + [ + a sh:ValidationResult ; + sh:focusNode ; + sh:resultMessage "Value does not have class core:Facet" ; + sh:resultPath core:hasFacet ; + sh:resultSeverity sh:Violation ; + sh:sourceConstraintComponent sh:ClassConstraintComponent ; + sh:sourceShape [ + sh:class core:Facet ; + sh:nodeKind sh:BlankNodeOrIRI ; + sh:path core:hasFacet ; + ] ; + sh:value [ + a location:LatLongCoordinates ; + location:latitude "48.860346"^^xsd:decimal ; + location:longitude "2.331199"^^xsd:decimal ; + ] ; + ] , + [ + a sh:ValidationResult ; + sh:focusNode [ + a location:SimpleAddressFacet ; + location:locality "Seattle" ; + location:postalCode "98052"^^xsd:integer ; + location:region "WA" ; + location:street "20341 Whitworth Institute 405 N. Whitworth" ; + ] ; + sh:resultMessage "Value is not Literal with datatype xsd:string" ; + sh:resultPath location:postalCode ; + sh:resultSeverity sh:Violation ; + sh:sourceConstraintComponent sh:DatatypeConstraintComponent ; + sh:sourceShape [ + sh:datatype xsd:string ; + sh:maxCount "1"^^xsd:integer ; + sh:nodeKind sh:Literal ; + sh:path location:postalCode ; + ] ; + sh:value "98052"^^xsd:integer ; + ] + ; + . diff --git a/tests/examples/relationship_PASS.json b/tests/examples/relationship_PASS.json new file mode 100644 index 00000000..674d9433 --- /dev/null +++ b/tests/examples/relationship_PASS.json @@ -0,0 +1,85 @@ +{ + "@context": { + "Action": "action:Action", + "ArchiveFile": "observable:ArchiveFile", + "File": "observable:File", + "FileFacet": "observable:FileFacet", + "ObservableRelationship": "observable:ObservableRelationship", + "Relationship": "core:Relationship", + "action": "https://unifiedcyberontology.org/ontology/uco/action#", + "core": "https://unifiedcyberontology.org/ontology/uco/core#", + "fileName": "observable:fileName", + "hasFacet": "core:hasFacet", + "isDirectional": "core:isDirectional", + "kb": "http://example.org/kb/", + "kindOfRelationship": "core:kindOfRelationship", + "observable": "https://unifiedcyberontology.org/ontology/uco/observable#", + "source": { + "@id": "core:source", + "@type": "@id" + }, + "target": { + "@id": "core:target", + "@type": "@id" + }, + "vocabulary": "https://unifiedcyberontology.org/ontology/uco/vocabulary#", + "xsd": "http://www.w3.org/2001/XMLSchema#" + }, + "@graph": [ + + { + "@id": "kb:relationship1", + "@type": "Relationship", + "isDirectional": true, + "kindOfRelationship": "CUSTOM_Influenced", + "source": "kb:file1", + "target": "kb:zipfile1" + }, + { + "@id": "kb:relationship2", + "@type": "ObservableRelationship", + "isDirectional": true, + "kindOfRelationship": { + "@type": "vocabulary:ObservableObjectRelationshipVocab", + "@value": "Contained_Within" + }, + "source": "kb:file1", + "target": "kb:zipfile1" + }, + { + "@id": "kb:relationship3", + "@type": "Relationship", + "isDirectional": true, + "kindOfRelationship": { + "@type": "vocabulary:ActionRelationshipVocab", + "@value": "Initiated" + }, + "source": "kb:action1", + "target": "kb:action2" + }, + { + "@id": "kb:action1", + "@type": "Action" + }, + { + "@id": "kb:action2", + "@type": "Action" + }, + { + "@id": "kb:file1", + "@type": "File", + "hasFacet": { + "@type": "FileFacet", + "fileName": "kindOfRelationship" + } + }, + { + "@id": "kb:zipfile1", + "@type": "ArchiveFile", + "hasFacet": { + "@type": "FileFacet", + "fileName": "Relationship" + } + } + ] +} diff --git a/tests/examples/relationship_PASS_validation.ttl b/tests/examples/relationship_PASS_validation.ttl new file mode 100644 index 00000000..9140ef2b --- /dev/null +++ b/tests/examples/relationship_PASS_validation.ttl @@ -0,0 +1,45 @@ +@prefix core: . +@prefix owl: . +@prefix rdf: . +@prefix rdfs: . +@prefix sh: . +@prefix vocabulary: . +@prefix xsd: . + +[] + a sh:ValidationReport ; + sh:conforms "false"^^xsd:boolean ; + sh:result + [ + a sh:ValidationResult ; + sh:focusNode ; + sh:resultMessage "Value is not Literal with datatype xsd:string" ; + sh:resultPath core:kindOfRelationship ; + sh:resultSeverity sh:Violation ; + sh:sourceConstraintComponent sh:DatatypeConstraintComponent ; + sh:sourceShape [ + sh:datatype xsd:string ; + sh:maxCount "1"^^xsd:integer ; + sh:nodeKind sh:Literal ; + sh:path core:kindOfRelationship ; + ] ; + sh:value "Contained_Within"^^vocabulary:ObservableObjectRelationshipVocab ; + ] , + [ + a sh:ValidationResult ; + sh:focusNode ; + sh:resultMessage "Value is not Literal with datatype xsd:string" ; + sh:resultPath core:kindOfRelationship ; + sh:resultSeverity sh:Violation ; + sh:sourceConstraintComponent sh:DatatypeConstraintComponent ; + sh:sourceShape [ + sh:datatype xsd:string ; + sh:maxCount "1"^^xsd:integer ; + sh:nodeKind sh:Literal ; + sh:path core:kindOfRelationship ; + ] ; + sh:value "Initiated"^^vocabulary:ActionRelationshipVocab ; + ] + ; + . + diff --git a/tests/examples/relationship_PASS_via_rdf_toolkit.ttl b/tests/examples/relationship_PASS_via_rdf_toolkit.ttl new file mode 100644 index 00000000..c8521251 --- /dev/null +++ b/tests/examples/relationship_PASS_via_rdf_toolkit.ttl @@ -0,0 +1,58 @@ +@prefix action: . +@prefix core: . +@prefix kb: . +@prefix observable: . +@prefix owl: . +@prefix rdf: . +@prefix rdfs: . +@prefix vocabulary: . +@prefix xsd: . + +kb:action1 + a action:Action ; + . + +kb:action2 + a action:Action ; + . + +kb:file1 + a observable:File ; + core:hasFacet [ + a observable:FileFacet ; + observable:fileName "kindOfRelationship" ; + ] ; + . + +kb:relationship1 + a core:Relationship ; + core:isDirectional "true"^^xsd:boolean ; + core:kindOfRelationship "CUSTOM_Influenced" ; + core:source kb:file1 ; + core:target kb:zipfile1 ; + . + +kb:relationship2 + a observable:ObservableRelationship ; + core:isDirectional "true"^^xsd:boolean ; + core:kindOfRelationship "Contained_Within"^^vocabulary:ObservableObjectRelationshipVocab ; + core:source kb:file1 ; + core:target kb:zipfile1 ; + . + +kb:relationship3 + a core:Relationship ; + core:isDirectional "true"^^xsd:boolean ; + core:kindOfRelationship "Initiated"^^vocabulary:ActionRelationshipVocab ; + core:source kb:action1 ; + core:target kb:action2 ; + . + +kb:zipfile1 + a observable:ArchiveFile ; + core:hasFacet [ + a observable:FileFacet ; + observable:fileName "Relationship" ; + ] ; + . + diff --git a/tests/examples/relationship_PASS_via_rdf_toolkit_validation_after_translation.ttl b/tests/examples/relationship_PASS_via_rdf_toolkit_validation_after_translation.ttl new file mode 100644 index 00000000..9140ef2b --- /dev/null +++ b/tests/examples/relationship_PASS_via_rdf_toolkit_validation_after_translation.ttl @@ -0,0 +1,45 @@ +@prefix core: . +@prefix owl: . +@prefix rdf: . +@prefix rdfs: . +@prefix sh: . +@prefix vocabulary: . +@prefix xsd: . + +[] + a sh:ValidationReport ; + sh:conforms "false"^^xsd:boolean ; + sh:result + [ + a sh:ValidationResult ; + sh:focusNode ; + sh:resultMessage "Value is not Literal with datatype xsd:string" ; + sh:resultPath core:kindOfRelationship ; + sh:resultSeverity sh:Violation ; + sh:sourceConstraintComponent sh:DatatypeConstraintComponent ; + sh:sourceShape [ + sh:datatype xsd:string ; + sh:maxCount "1"^^xsd:integer ; + sh:nodeKind sh:Literal ; + sh:path core:kindOfRelationship ; + ] ; + sh:value "Contained_Within"^^vocabulary:ObservableObjectRelationshipVocab ; + ] , + [ + a sh:ValidationResult ; + sh:focusNode ; + sh:resultMessage "Value is not Literal with datatype xsd:string" ; + sh:resultPath core:kindOfRelationship ; + sh:resultSeverity sh:Violation ; + sh:sourceConstraintComponent sh:DatatypeConstraintComponent ; + sh:sourceShape [ + sh:datatype xsd:string ; + sh:maxCount "1"^^xsd:integer ; + sh:nodeKind sh:Literal ; + sh:path core:kindOfRelationship ; + ] ; + sh:value "Initiated"^^vocabulary:ActionRelationshipVocab ; + ] + ; + . + diff --git a/tests/examples/relationship_PASS_via_rdflib.ttl b/tests/examples/relationship_PASS_via_rdflib.ttl new file mode 100644 index 00000000..c8521251 --- /dev/null +++ b/tests/examples/relationship_PASS_via_rdflib.ttl @@ -0,0 +1,58 @@ +@prefix action: . +@prefix core: . +@prefix kb: . +@prefix observable: . +@prefix owl: . +@prefix rdf: . +@prefix rdfs: . +@prefix vocabulary: . +@prefix xsd: . + +kb:action1 + a action:Action ; + . + +kb:action2 + a action:Action ; + . + +kb:file1 + a observable:File ; + core:hasFacet [ + a observable:FileFacet ; + observable:fileName "kindOfRelationship" ; + ] ; + . + +kb:relationship1 + a core:Relationship ; + core:isDirectional "true"^^xsd:boolean ; + core:kindOfRelationship "CUSTOM_Influenced" ; + core:source kb:file1 ; + core:target kb:zipfile1 ; + . + +kb:relationship2 + a observable:ObservableRelationship ; + core:isDirectional "true"^^xsd:boolean ; + core:kindOfRelationship "Contained_Within"^^vocabulary:ObservableObjectRelationshipVocab ; + core:source kb:file1 ; + core:target kb:zipfile1 ; + . + +kb:relationship3 + a core:Relationship ; + core:isDirectional "true"^^xsd:boolean ; + core:kindOfRelationship "Initiated"^^vocabulary:ActionRelationshipVocab ; + core:source kb:action1 ; + core:target kb:action2 ; + . + +kb:zipfile1 + a observable:ArchiveFile ; + core:hasFacet [ + a observable:FileFacet ; + observable:fileName "Relationship" ; + ] ; + . + diff --git a/tests/examples/relationship_PASS_via_rdflib_validation_after_translation.ttl b/tests/examples/relationship_PASS_via_rdflib_validation_after_translation.ttl new file mode 100644 index 00000000..9140ef2b --- /dev/null +++ b/tests/examples/relationship_PASS_via_rdflib_validation_after_translation.ttl @@ -0,0 +1,45 @@ +@prefix core: . +@prefix owl: . +@prefix rdf: . +@prefix rdfs: . +@prefix sh: . +@prefix vocabulary: . +@prefix xsd: . + +[] + a sh:ValidationReport ; + sh:conforms "false"^^xsd:boolean ; + sh:result + [ + a sh:ValidationResult ; + sh:focusNode ; + sh:resultMessage "Value is not Literal with datatype xsd:string" ; + sh:resultPath core:kindOfRelationship ; + sh:resultSeverity sh:Violation ; + sh:sourceConstraintComponent sh:DatatypeConstraintComponent ; + sh:sourceShape [ + sh:datatype xsd:string ; + sh:maxCount "1"^^xsd:integer ; + sh:nodeKind sh:Literal ; + sh:path core:kindOfRelationship ; + ] ; + sh:value "Contained_Within"^^vocabulary:ObservableObjectRelationshipVocab ; + ] , + [ + a sh:ValidationResult ; + sh:focusNode ; + sh:resultMessage "Value is not Literal with datatype xsd:string" ; + sh:resultPath core:kindOfRelationship ; + sh:resultSeverity sh:Violation ; + sh:sourceConstraintComponent sh:DatatypeConstraintComponent ; + sh:sourceShape [ + sh:datatype xsd:string ; + sh:maxCount "1"^^xsd:integer ; + sh:nodeKind sh:Literal ; + sh:path core:kindOfRelationship ; + ] ; + sh:value "Initiated"^^vocabulary:ActionRelationshipVocab ; + ] + ; + . + diff --git a/tests/examples/relationship_XFAIL.json b/tests/examples/relationship_XFAIL.json new file mode 100644 index 00000000..f3786ce4 --- /dev/null +++ b/tests/examples/relationship_XFAIL.json @@ -0,0 +1,70 @@ +{ + "@context": { + "action": "https://unifiedcyberontology.org/ontology/uco/action#", + "core": "https://unifiedcyberontology.org/ontology/uco/core#", + "kb": "http://example.org/kb/", + "observable": "https://unifiedcyberontology.org/ontology/uco/observable#", + "vocabulary": "https://unifiedcyberontology.org/ontology/uco/vocabulary#", + "xsd": "http://www.w3.org/2001/XMLSchema#" + }, + "@graph": [ + { + "@id": "kb:relationship1", + "@type": "core:Relationship", + "rdfs:comment": "'CUSTOM_Influenced' should be flagged as not a member of ObservableObjectRelationshipVocab.", + "core:isDirectional": true, + "core:kindOfRelationship": { + "@type": "vocabulary:ObservableObjectRelationshipVocab", + "@value": "CUSTOM_Influenced" + }, + "core:source": { + "@id": "kb:file1" + }, + "core:target": { + "@id": "kb:zipfile1" + } + }, + { + "@id": "kb:relationship2", + "@type": "observable:ObservableRelationship", + "rdfs:comment": "'Contained_Within' should be flagged as a member of ObservableObjectRelationshipVocab.", + "core:isDirectional": true, + "core:kindOfRelationship": "Contained_Within", + "core:source": { + "@id": "kb:file1" + }, + "core:target": { + "@id": "kb:zipfile1" + } + }, + { + "@id": "kb:relationship3", + "@type": "core:Relationship", + "rdfs:comment": "'Contained_Within' should be flagged as a member of ActionRelationshipVocab.", + "core:isDirectional": true, + "core:kindOfRelationship": "Initiated", + "core:source": { + "@id": "kb:action1" + }, + "core:target": { + "@id": "kb:action2" + } + }, + { + "@id": "kb:action1", + "@type": "action:Action" + }, + { + "@id": "kb:action2", + "@type": "action:Action" + }, + { + "@id": "kb:file1", + "@type": "observable:File" + }, + { + "@id": "kb:zipfile1", + "@type": "observable:ArchiveFile" + } + ] +} diff --git a/tests/examples/relationship_XFAIL_validation.ttl b/tests/examples/relationship_XFAIL_validation.ttl new file mode 100644 index 00000000..3a4afa91 --- /dev/null +++ b/tests/examples/relationship_XFAIL_validation.ttl @@ -0,0 +1,28 @@ +@prefix core: . +@prefix owl: . +@prefix rdf: . +@prefix rdfs: . +@prefix sh: . +@prefix vocabulary: . +@prefix xsd: . + +[] + a sh:ValidationReport ; + sh:conforms "false"^^xsd:boolean ; + sh:result [ + a sh:ValidationResult ; + sh:focusNode ; + sh:resultMessage "Value is not Literal with datatype xsd:string" ; + sh:resultPath core:kindOfRelationship ; + sh:resultSeverity sh:Violation ; + sh:sourceConstraintComponent sh:DatatypeConstraintComponent ; + sh:sourceShape [ + sh:datatype xsd:string ; + sh:maxCount "1"^^xsd:integer ; + sh:nodeKind sh:Literal ; + sh:path core:kindOfRelationship ; + ] ; + sh:value "CUSTOM_Influenced"^^vocabulary:ObservableObjectRelationshipVocab ; + ] ; + . + diff --git a/tests/examples/test_validation.py b/tests/examples/test_validation.py index da70c354..5bd41f8e 100644 --- a/tests/examples/test_validation.py +++ b/tests/examples/test_validation.py @@ -61,14 +61,17 @@ def load_validation_graph( def confirm_validation_errors( filename : str, - expected_error_iris : typing.Set[str] + *, + expected_error_iris : typing.Optional[typing.Set[str]] = None, + expected_focus_nodes : typing.Optional[typing.Set[str]] = None ): g = load_validation_graph(filename, False) computed_error_iris = set() + computed_focus_nodes = set() query = rdflib.plugins.sparql.prepareQuery("""\ -SELECT DISTINCT ?nResultPath +SELECT DISTINCT ?nFocusNode ?nResultPath WHERE { ?nReport a sh:ValidationReport ; @@ -77,20 +80,30 @@ def confirm_validation_errors( ?nValidationResult a sh:ValidationResult ; + sh:focusNode ?nFocusNode ; sh:resultPath ?nResultPath ; . } """, initNs=NSDICT) for result in g.query(query): - (n_result_path,) = result + (n_focus_node, n_result_path) = result + computed_focus_nodes.add(str(n_focus_node)) computed_error_iris.add(str(n_result_path)) - try: - assert expected_error_iris == computed_error_iris - except: - logging.error("Please review %s and its associated .json file to identify the ground truth validation error mismatch pertaining to data properties noted in this function.", filename) - raise + if not expected_error_iris is None: + try: + assert expected_error_iris == computed_error_iris + except: + logging.error("Please review %s and its associated .json file to identify the ground truth validation error mismatch pertaining to data properties noted in this function.", filename) + raise + + if not expected_focus_nodes is None: + try: + assert expected_focus_nodes == computed_focus_nodes + except: + logging.error("Please review %s and its associated .json file to identify the ground truth validation error mismatch pertaining to focus nodes noted in this function.", filename) + raise def test_action_inheritance_PASS_validation(): """ @@ -105,7 +118,7 @@ def test_action_inheritance_XFAIL_validation(): """ confirm_validation_errors( "action_inheritance_XFAIL_validation.ttl", - { + expected_error_iris={ str(NS_UCO_ACTION.action), str(NS_UCO_ACTION.actionStatus) } @@ -131,7 +144,7 @@ def test_location_XFAIL_validation(): """ confirm_validation_errors( "location_XFAIL_validation.ttl", - { + expected_error_iris={ str(NS_UCO_CORE.hasFacet), str(NS_UCO_LOCATION.postalCode) } @@ -145,7 +158,35 @@ def test_location_XFAIL_validation_XPASS_wrong_concept_name(): """ confirm_validation_errors( "location_XFAIL_validation.ttl", - { + expected_error_iris={ str(NS_UCO_CORE.descriptionButWrongName) } ) + +def test_relationship_PASS_validation(): + """ + Confirm the PASS instance data passes validation. + """ + g = load_validation_graph("relationship_PASS_validation.ttl", True) + assert isinstance(g, rdflib.Graph) + +def test_relationship_XFAIL_validation(): + """ + Confirm the PASS instance data passes validation. + """ + confirm_validation_errors( + "relationship_XFAIL_validation.ttl", + expected_focus_nodes={ + "http://example.org/kb/relationship1", + "http://example.org/kb/relationship2", + "http://example.org/kb/relationship3" + } + ) + +def test_relationship_PASS_via_rdf_toolkit_validation_after_translation(): + g = load_validation_graph("relationship_PASS_via_rdf_toolkit_validation_after_translation.ttl", True) + assert isinstance(g, rdflib.Graph) + +def relationship_PASS_via_rdflib_validation_after_translation(): + g = load_validation_graph("relationship_PASS_via_rdflib_validation_after_translation.ttl", True) + assert isinstance(g, rdflib.Graph) diff --git a/tests/src/glom_graph.py b/tests/src/glom_graph.py index 7ec47b81..8b5391f2 100644 --- a/tests/src/glom_graph.py +++ b/tests/src/glom_graph.py @@ -27,8 +27,8 @@ def main(): g = rdflib.Graph() for in_graph in args.in_graph: - g.parse(in_graph, format="turtle") - g.serialize(args.out_graph, format="turtle") + g.parse(in_graph) + g.serialize(args.out_graph) if __name__ == "__main__": import argparse