uoa-validator-engine2/src/test/groovy/eu/dnetlib/validator2/validation/guideline/SyntheticGuidelineSpecifica...

168 lines
7.1 KiB
Groovy

package eu.dnetlib.validator2.validation.guideline
import eu.dnetlib.validator2.engine.Rule
import eu.dnetlib.validator2.engine.Status
import eu.dnetlib.validator2.engine.XMLHelper
import eu.dnetlib.validator2.engine.builtins.XMLCardinalityRule
import org.w3c.dom.Document
import spock.lang.Shared
import spock.lang.Specification
import spock.lang.Unroll
import spock.util.concurrent.AsyncConditions
import java.util.concurrent.Executors
class SyntheticGuidelineSpecification extends Specification {
@Shared
def xmlCardinalityRule = XMLCardinalityRule.
builder().
setId("1").
setRange(0, 5).
setXPathExpression("//*[name()='ns:attr' and @id='cardinality-3']").
build()
def "Synthetic guideline returns expected Guideline from valid inputs with ElementSpec"() {
given: "initial values"
def name = "SynthGuideline name"
def weight = 10
def elementName = "testElement"
def cardinality = Cardinality.ONE
def elementSpec = Builders.forMandatoryElement(elementName, cardinality).build()
when: "a SyntheticGuideline is created with these inputs"
def syntheticGuideline = SyntheticGuideline.of(name, weight, elementSpec)
then: "results are expected and no errors occur"
noExceptionThrown()
syntheticGuideline != null
syntheticGuideline.getName() == name
syntheticGuideline.getWeight() == weight
// compilationResult is tested in ElementSpecCompiler
}
def "Synthetic guideline returns expected Guideline from valid inputs with rule"() {
given: "initial values"
def name = "SynthGuideline name"
def weight = 10
def reqLevel = RequirementLevel.MANDATORY
when: "a SyntheticGuideline is created with these inputs and a rule"
def syntheticGuideline = SyntheticGuideline.of(name, weight, reqLevel, xmlCardinalityRule)
then: "results are expected and no errors occur"
noExceptionThrown()
syntheticGuideline != null
syntheticGuideline.getName() == name
syntheticGuideline.getWeight() == weight
syntheticGuideline.compilationResult.rootNodeRule.getContext() == xmlCardinalityRule.getContext()
syntheticGuideline.compilationResult.nodeRules.size() == 0
}
@Unroll
def "SyntheticGuidelines validates properly against doc: #testDoc"() {
given: "an elementSpec"
def elementSpec = Builders.
forMandatoryElement("testElement", Cardinality.ONE).
withOptionalAttribute("testAttr").
build()
and: "initial values"
def syntheticGuideline = SyntheticGuideline.of("SynthGuideline name", 5, elementSpec)
Document doc = XMLHelper.parse("/eu/dnetlib/validator2/validation/guideline/$testDoc")
when: "validating guideline against a doc"
def result = syntheticGuideline.validate(doc)
then: "expected validation result is returned"
result.status() == resultStatus
result.score() == resultScore
result.errors().size() == errors
result.warnings().size() == warnings
result.internalError() == null
where:
testDoc || resultStatus | resultScore | errors | warnings
"synthetic-guideline-spec-success.xml" || Status.SUCCESS | 5 | 0 | 0
"synthetic-guideline-spec-success-with-warnings.xml" || Status.SUCCESS | 5 | 0 | 1
"synthetic-guideline-spec-failure.xml" || Status.FAILURE | 0 | 1 | 0
//TODO: Need to test for internal error? I assume it would not be that easy...
}
@Unroll
def "SyntheticGuideline validates invalid inputs name: #name, weight: #weight, elementSpec: #elementSpec"() {
when: "creating SyntheticGuideline with invalid parameters"
SyntheticGuideline.of(name, weight, elementSpec)
then: "relevant error occurs"
def error = thrown(expectedException)
error.message == expectedMessage
where:
name | weight | elementSpec || expectedException | expectedMessage
"" | 5 | Mock(ElementSpec) || IllegalArgumentException | "Name cannot be empty"
null | 5 | Mock(ElementSpec) || IllegalArgumentException | "Name cannot be empty"
"valid" | -1 | Mock(ElementSpec) || IllegalArgumentException | "Weight cannot be negative"
"valid" | 0 | null || IllegalArgumentException | "ElementSpec cannot be empty"
}
@Unroll
def "SyntheticGuideline validates invalid inputs name: #name, weight: #weight, requirementLevel: #requirementLevel, 1 rule: #rule1"() {
when: "creating SyntheticGuideline with invalid parameters with a single rule"
SyntheticGuideline.of(name, weight, requirementLevel, rule)
then: "relevant error occurs"
def error = thrown(expectedException)
error.message == expectedMessage
where:
name | weight | requirementLevel | rule || expectedException | expectedMessage
"" | 1 | RequirementLevel.OPTIONAL | Mock(Rule) || IllegalArgumentException | "Name cannot be empty"
null | 2 | RequirementLevel.OPTIONAL | Mock(Rule) || IllegalArgumentException | "Name cannot be empty"
"valid" | -1 | RequirementLevel.OPTIONAL | Mock(Rule) || IllegalArgumentException | "Weight cannot be negative"
"valid" | 0 | null | Mock(Rule) || IllegalArgumentException | "Requirement level cannot be empty"
"valid" | 3 | RequirementLevel.OPTIONAL | null || IllegalArgumentException | "Rule cannot be empty"
}
def "SyntheticGuidelines can be run by multiple threads"() {
given:
int count = 100
def futures = []
def conditions = new AsyncConditions(count)
def executor = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors())
def elementSpec = Builders.
forMandatoryElement("testElement", Cardinality.ONE).
withOptionalAttribute("testAttr").
build()
def syntheticGuideline = SyntheticGuideline.of("SynthGuideline name", 5, elementSpec)
Document doc = XMLHelper.parse("/eu/dnetlib/validator2/validation/guideline/synthetic-guideline-spec-success.xml")
when:
for(int i = 0; i < count; i++) {
def threadMessage = "Thread-$i"
futures << executor.submit {
println threadMessage
Guideline.Result result = syntheticGuideline.validate(doc)
conditions.evaluate {
assert result.status() == Status.SUCCESS &&
result.score() == 5 &&
result.errors().size() == 0 &&
result.warnings().size() == 0 &&
result.internalError() == null
}
}
}
then:
futures.size() == count
conditions.await(2)
cleanup:
executor.shutdownNow()
}
}