168 lines
7.1 KiB
Groovy
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()
|
|
}
|
|
|
|
}
|