Skip to content

Commit

Permalink
Halting tests
Browse files Browse the repository at this point in the history
  • Loading branch information
ulitol97 committed Apr 26, 2022
1 parent bd00e1f commit ac0f88c
Show file tree
Hide file tree
Showing 3 changed files with 193 additions and 42 deletions.
93 changes: 93 additions & 0 deletions src/test/scala/utils/Samples.scala
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,16 @@ import TestData.shapeMapStr
import Utils.{dateFormatter, mkRdfItem}
import data.DataFormat
import data.DataFormat.*
import implicits.RDFElementImplicits.rdfFromString
import schema.ShExSchemaFormat
import schema.ShExSchemaFormat.{SHEXC, SHEXJ}
import stream.extractors.list.ListExtractor
import trigger.ShapeMapFormat.{COMPACT, JSON}
import trigger.{ShapeMapFormat, TriggerShapeMap, TriggerTargetDeclarations, ValidationTrigger}
import utils.Samples.RdfSamples.dateFormatter
import validation.Validator
import validation.configuration.ValidatorConfiguration
import validation.result.ValidationResult

import cats.effect.IO
import es.weso.schema.{Schema, Schemas}
Expand Down Expand Up @@ -53,6 +58,94 @@ object Samples {
*/
private val maxValidTemperature: Double = 20.00

/**
* Utils to create validation streams for testing
*/
object StreamSamples {
/**
* Similar to the alternative implementation of [[mkSingleValidationResult]],
* but here the RDF string is not passed manually but created from a template
* given its desired format
*
* @param rdfFormat Format of the RDF item that we want to get validated,
* generated from template (see [[RdfSamples]])
* @param schemaFormat Format of the Schema to be used for validation,
* generated from template (see [[SchemaSamples]])
* @param valid Whether if the produced RDF item should comply with
* the produced validation schema or not
* Used to control de output status of the validation
* @param haltOnInvalid Whether if the underlying validator should halt on
* INVALID validation results
* @param haltOnError Whether if the underlying validator should halt on
* ERRORED validation results
* @return The [[ValidationResult]] of getting an RDF item (of format [[rdfFormat]])
* through a validator using a Schema (of format/engine [[schemaFormat]])
* following the data, schema and trigger templates in [[Samples]]
*/
def mkSingleValidationResult(rdfFormat: DataFormat,
schemaFormat: DataFormat | ShExSchemaFormat,
valid: Boolean = true,
haltOnInvalid: Boolean = false,
haltOnError: Boolean = false
): IO[ValidationResult] = {
// Make the RDF item
val rdfItem = RdfSamples.mkRdfItem(rdfFormat, valid = valid)
// Resort to alternative implementation
mkSingleValidationResult(rdfItem, rdfFormat, schemaFormat, haltOnInvalid, haltOnError)
}

/**
* Shortcut for generating single-item results through comet's stream validators,
* which is the main logic required for these tests
*
* Given the details of the validation (input data/schema format, wanted result...)
* this creates a validation stream that complies with it and gets its eventual
* result back
*
* @param rdfItem Custom string of RDF data provided for validation
* @param rdfFormat Format of the RDF string provided for validation
* @param schemaFormat Format of the Schema to be used for validation,
* generated from template (see [[SchemaSamples]])
* @param haltOnInvalid Whether if the underlying validator should halt on
* INVALID validation results
* @param haltOnError Whether if the underlying validator should halt on
* ERRORED validation results
* @return The [[ValidationResult]] of getting a custom RDF string, expected
* to have format [[rdfFormat]],
* through a validator using a Schema (of format/engine [[schemaFormat]])
* following the schema and trigger templates in [[Samples]]
*/
def mkSingleValidationResult(rdfItem: String,
rdfFormat: DataFormat,
schemaFormat: DataFormat | ShExSchemaFormat,
haltOnInvalid: Boolean,
haltOnError: Boolean
): IO[ValidationResult] = {
for {
// Make the schema
schema <- schemaFormat match {
case df: DataFormat => SchemaSamples.mkSchemaShaclIO(df)
case sf: ShExSchemaFormat => SchemaSamples.mkSchemaShExIO(sf)
}
// Make the validation trigger (inferred from schema type)
trigger = schemaFormat match {
case _: DataFormat => TriggerSamples.mkTriggerShacl
case _: ShExSchemaFormat => TriggerSamples.mkTriggerShex(COMPACT)
}
// Get the RDF item into a list extractor
extractor = ListExtractor(items = List(rdfItem), format = rdfFormat)

// Open validation stream and collect the validation results
// Validator settings
validatorConfiguration = ValidatorConfiguration(schema, trigger,
haltOnInvalid = haltOnInvalid, haltOnErrored = haltOnError)
validator = Validator(validatorConfiguration, extractor)
results: List[ValidationResult] <- validator.validate.compile.toList
} yield results.head
}

}

/**
* Utils to create RDF data Strings for testing
*/
Expand Down
99 changes: 99 additions & 0 deletions src/test/scala/validation/halting/HaltingTests.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
package org.ragna.comet
package validation.halting

import data.DataFormat
import data.DataFormat.*
import exception.stream.validations.{StreamErroredItemException, StreamInvalidItemException}
import implicits.RDFElementImplicits.rdfFromString
import schema.ShExSchemaFormat
import schema.ShExSchemaFormat.*
import stream.extractors.StreamExtractor
import stream.extractors.list.ListExtractor
import trigger.ShapeMapFormat.*
import trigger.TriggerModeType.{SHAPEMAP, TARGET_DECLARATIONS}
import trigger.{ShapeMapFormat, TriggerModeType, ValidationTrigger}
import utils.Samples.StreamSamples.mkSingleValidationResult
import validation.Validator
import validation.configuration.ValidatorConfiguration
import validation.ouputs.SchemaTests
import validation.result.ResultStatus.*
import validation.result.ValidationResult

import cats.effect.IO
import cats.effect.testing.scalatest.AsyncIOSpec
import es.weso.schema.Schema
import org.scalatest.freespec.AsyncFreeSpec
import org.scalatest.matchers.should.Matchers

/**
* Test suite checking that the validation mechanism halts when configured to
* do so for either invalid or erroring validations using ShEx or SHACL schemas
*
* The testing goes as follows:
*
* - The same RDF data example will be validated against a given schema,
* though slightly modified to test both invalid and erroring validations
*
* - Single RDF items will be tested as a single item stream
* fed to a stream-validator to check that the results are the expected ones
*
* - The List extractor will be used for testing, since it is the simplest way
* we have to test in-memory data
*
* Tests are nested as follows to cover all possibilities:
*
* - Per expected behaviour (halt on invalid, halt on errored)
* - Per Schema type/engine (ShEx, SHACL, etc.)
*
* @note We understand as invalid validations those whose result is INVALID,
* whereas errored validations are those who cannot be completed due to
* an error in the validation process (nomally due to bad data/schema
* syntax)
* @note Standard behaviour (not halting on VALID items) is not tested here
* since it is already exhaustively tested in [[SchemaTests]]
*/
//noinspection RedundantDefaultArgument
class HaltingTests extends AsyncFreeSpec with AsyncIOSpec with Matchers {

"Validation halts on INVALID" - {
"using ShEx schemas" in {
mkSingleValidationResult(
rdfFormat = TURTLE,
schemaFormat = SHEXC,
valid = false,
haltOnInvalid = true)
.assertThrows[StreamInvalidItemException]
}

"using SHACL schemas" in {
mkSingleValidationResult(
rdfFormat = TURTLE,
schemaFormat = TURTLE,
valid = false,
haltOnInvalid = true)
.assertThrows[StreamInvalidItemException]
}
}

"Validation halts on ERRORED" - {
"using ShEx schemas" in {
mkSingleValidationResult(
rdfItem = "This is wrong RDF data that will not validate whatsoever",
rdfFormat = TURTLE,
schemaFormat = SHEXC,
haltOnInvalid = false,
haltOnError = true)
.assertThrows[StreamErroredItemException]
}

"using SHACL schemas" in {
mkSingleValidationResult(
rdfItem = "This is wrong RDF data that will not validate whatsoever",
rdfFormat = TURTLE,
schemaFormat = TURTLE,
haltOnInvalid = false,
haltOnError = true)
.assertThrows[StreamErroredItemException]
}
}
}
43 changes: 1 addition & 42 deletions src/test/scala/validation/ouputs/SchemaTests.scala
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import stream.extractors.list.ListExtractor
import trigger.ShapeMapFormat.*
import trigger.TriggerModeType.{SHAPEMAP, TARGET_DECLARATIONS}
import trigger.{ShapeMapFormat, TriggerModeType, ValidationTrigger}
import utils.Samples
import utils.Samples.StreamSamples.mkSingleValidationResult
import validation.Validator
import validation.configuration.ValidatorConfiguration
import validation.result.ResultStatus.*
Expand Down Expand Up @@ -55,47 +55,6 @@ import org.scalatest.matchers.should.Matchers
//noinspection RedundantDefaultArgument
class SchemaTests extends AsyncFreeSpec with AsyncIOSpec with Matchers {

/**
* Shortcut for generating single-item results through comet's stream validators,
* which is the main logic required for these tests
*
* Given the details of the validation (input data/schema format, wanted result...)
* this creates a validation stream that complies with it and gets its eventual
* result back
*
* @param rdfFormat Format of the RDF item that we want to get through validation
* @param schemaFormat Format of the Schema to be used for validation
* @param valid Whether if the produced RDF item should throw a VALID validation
* result or not
* @return The [[ValidationResult]] of getting an RDF item (of format [[rdfFormat]])
* through a validator using a Schema (of format/engine [[schemaFormat]])
* following the data and schema templates in [[Samples]]
*/
private def mkSingleValidationResult(rdfFormat: DataFormat,
schemaFormat: DataFormat | ShExSchemaFormat,
valid: Boolean = true): IO[ValidationResult] = {
for {
// Make the schema
schema <- schemaFormat match {
case df: DataFormat => Samples.SchemaSamples.mkSchemaShaclIO(df)
case sf: ShExSchemaFormat => Samples.SchemaSamples.mkSchemaShExIO(sf)
}
// Make the validation trigger (inferred from schema type)
trigger = schemaFormat match {
case _: DataFormat => Samples.TriggerSamples.mkTriggerShacl
case _: ShExSchemaFormat => Samples.TriggerSamples.mkTriggerShex(COMPACT)
}
// Make the RDF item and get it into a list extractor
rdfItem = Samples.RdfSamples.mkRdfItem(rdfFormat, valid = valid)
extractor = ListExtractor(items = List(rdfItem), format = rdfFormat)

// Open validation stream and collect the validation results
validator = Validator(extractor, schema, trigger)
results: List[ValidationResult] <- validator.validate.compile.toList
_ <- if (!valid) IO.println(results.head) else IO.unit
} yield results.head
}

"ShEx schemas" - {
"using ShExC syntax" - {
"validate VALID RDF data" - {
Expand Down

0 comments on commit ac0f88c

Please sign in to comment.