2012-10-19 15:23:34 +02:00
import os
from lxml import etree
from nose . tools import assert_equal , assert_in
from ckanext . spatial import validation
# other validation tests are in test_harvest.py
2020-04-15 01:20:30 +02:00
class TestValidation ( object ) :
2012-11-19 18:15:16 +01:00
def _get_file_path ( self , file_name ) :
2020-04-15 01:20:30 +02:00
return os . path . join ( os . path . dirname ( __file__ ) , " xml " , file_name )
2012-11-19 18:15:16 +01:00
2012-10-19 15:23:34 +02:00
def get_validation_errors ( self , validator , validation_test_filename ) :
2020-04-15 01:20:30 +02:00
validation_test_filepath = self . _get_file_path (
validation_test_filename
)
2012-10-19 15:23:34 +02:00
xml = etree . parse ( validation_test_filepath )
is_valid , errors = validator . is_valid ( xml )
2012-11-19 18:15:16 +01:00
2020-04-15 01:20:30 +02:00
return " ; " . join ( [ e [ 0 ] for e in errors ] )
2012-10-19 15:23:34 +02:00
def test_iso19139_failure ( self ) :
2020-04-15 01:20:30 +02:00
errors = self . get_validation_errors (
validation . ISO19139Schema , " iso19139/dataset-invalid.xml "
)
2012-10-19 15:23:34 +02:00
assert len ( errors ) > 0
2020-04-15 01:20:30 +02:00
assert_in ( " Dataset schema (gmx.xsd) " , errors )
assert_in (
" { http://www.isotc211.org/2005/gmd}nosuchelement ' : This element is not expected. " ,
errors ,
)
2012-10-19 15:23:34 +02:00
def test_iso19139_pass ( self ) :
2020-04-15 01:20:30 +02:00
errors = self . get_validation_errors (
validation . ISO19139Schema , " iso19139/dataset.xml "
)
assert_equal ( errors , " " )
2012-10-19 15:23:34 +02:00
# Gemini2.1 tests are basically the same as those in test_harvest.py but
# a few little differences make it worth not removing them in
# test_harvest
def test_01_dataset_fail_iso19139_schema ( self ) :
2020-04-15 01:20:30 +02:00
errors = self . get_validation_errors (
validation . ISO19139EdenSchema ,
" gemini2.1/validation/01_Dataset_Invalid_XSD_No_Such_Element.xml " ,
)
2012-10-19 15:23:34 +02:00
assert len ( errors ) > 0
2020-04-15 01:20:30 +02:00
assert_in ( " (gmx.xsd) " , errors )
assert_in (
" ' { http://www.isotc211.org/2005/gmd}nosuchelement ' : This element is not expected. " ,
errors ,
)
2012-10-19 15:23:34 +02:00
def test_02_dataset_fail_constraints_schematron ( self ) :
2020-04-15 01:20:30 +02:00
errors = self . get_validation_errors (
validation . ConstraintsSchematron14 ,
" gemini2.1/validation/02_Dataset_Invalid_19139_Missing_Data_Format.xml " ,
)
2012-10-19 15:23:34 +02:00
assert len ( errors ) > 0
2020-04-15 01:20:30 +02:00
assert_in (
" MD_Distribution / MD_Format: count(distributionFormat + distributorFormat) > 0 " ,
errors ,
)
2012-10-19 15:23:34 +02:00
def test_03_dataset_fail_gemini_schematron ( self ) :
2020-04-15 01:20:30 +02:00
errors = self . get_validation_errors (
validation . Gemini2Schematron ,
" gemini2.1/validation/03_Dataset_Invalid_GEMINI_Missing_Keyword.xml " ,
)
2012-10-19 15:23:34 +02:00
assert len ( errors ) > 0
2020-04-15 01:20:30 +02:00
assert_in ( " Descriptive keywords are mandatory " , errors )
2012-10-19 15:23:34 +02:00
def assert_passes_all_gemini2_1_validation ( self , xml_filepath ) :
2020-04-15 01:20:30 +02:00
errs = self . get_validation_errors (
validation . ISO19139EdenSchema , xml_filepath
)
assert not errs , " ISO19139EdenSchema: " + errs
errs = self . get_validation_errors (
validation . ConstraintsSchematron14 , xml_filepath
)
assert not errs , " ConstraintsSchematron14: " + errs
errs = self . get_validation_errors (
validation . Gemini2Schematron , xml_filepath
)
assert not errs , " Gemini2Schematron: " + errs
2012-10-19 15:23:34 +02:00
def test_04_dataset_valid ( self ) :
2020-04-15 01:20:30 +02:00
self . assert_passes_all_gemini2_1_validation (
" gemini2.1/validation/04_Dataset_Valid.xml "
)
2012-10-19 15:23:34 +02:00
def test_05_series_fail_iso19139_schema ( self ) :
2020-04-15 01:20:30 +02:00
errors = self . get_validation_errors (
validation . ISO19139EdenSchema ,
" gemini2.1/validation/05_Series_Invalid_XSD_No_Such_Element.xml " ,
)
2012-10-19 15:23:34 +02:00
assert len ( errors ) > 0
2020-04-15 01:20:30 +02:00
assert_in ( " (gmx.xsd) " , errors )
assert_in (
" ' { http://www.isotc211.org/2005/gmd}nosuchelement ' : This element is not expected. " ,
errors ,
)
2012-10-19 15:23:34 +02:00
def test_06_series_fail_constraints_schematron ( self ) :
2020-04-15 01:20:30 +02:00
errors = self . get_validation_errors (
validation . ConstraintsSchematron14 ,
" gemini2.1/validation/06_Series_Invalid_19139_Missing_Data_Format.xml " ,
)
2012-10-19 15:23:34 +02:00
assert len ( errors ) > 0
2020-04-15 01:20:30 +02:00
assert_in (
" MD_Distribution / MD_Format: count(distributionFormat + distributorFormat) > 0 " ,
errors ,
)
2012-10-19 15:23:34 +02:00
def test_07_series_fail_gemini_schematron ( self ) :
2020-04-15 01:20:30 +02:00
errors = self . get_validation_errors (
validation . Gemini2Schematron ,
" gemini2.1/validation/07_Series_Invalid_GEMINI_Missing_Keyword.xml " ,
)
2012-10-19 15:23:34 +02:00
assert len ( errors ) > 0
2020-04-15 01:20:30 +02:00
assert_in ( " Descriptive keywords are mandatory " , errors )
2012-10-19 15:23:34 +02:00
def test_08_series_valid ( self ) :
2020-04-15 01:20:30 +02:00
self . assert_passes_all_gemini2_1_validation (
" gemini2.1/validation/08_Series_Valid.xml "
)
2012-10-19 15:23:34 +02:00
def test_09_service_fail_iso19139_schema ( self ) :
2020-04-15 01:20:30 +02:00
errors = self . get_validation_errors (
validation . ISO19139EdenSchema ,
" gemini2.1/validation/09_Service_Invalid_No_Such_Element.xml " ,
)
2012-10-19 15:23:34 +02:00
assert len ( errors ) > 0
2020-04-15 01:20:30 +02:00
assert_in ( " (gmx.xsd & srv.xsd) " , errors )
assert_in (
" ' { http://www.isotc211.org/2005/gmd}nosuchelement ' : This element is not expected. " ,
errors ,
)
2012-10-19 15:23:34 +02:00
def test_10_service_fail_constraints_schematron ( self ) :
2020-04-15 01:20:30 +02:00
errors = self . get_validation_errors (
validation . ConstraintsSchematron14 ,
" gemini2.1/validation/10_Service_Invalid_19139_Level_Description.xml " ,
)
2012-10-19 15:23:34 +02:00
assert len ( errors ) > 0
2020-04-15 01:20:30 +02:00
assert_in (
" DQ_Scope: ' levelDescription ' is mandatory if ' level ' notEqual ' dataset ' or ' series ' . " ,
errors ,
)
2012-10-19 15:23:34 +02:00
def test_11_service_fail_gemini_schematron ( self ) :
2020-04-15 01:20:30 +02:00
errors = self . get_validation_errors (
validation . Gemini2Schematron ,
" gemini2.1/validation/11_Service_Invalid_GEMINI_Service_Type.xml " ,
)
2012-10-19 15:23:34 +02:00
assert len ( errors ) > 0
2020-04-15 01:20:30 +02:00
assert_in (
" Service type shall be one of ' discovery ' , ' view ' , ' download ' , ' transformation ' , ' invoke ' or ' other ' following INSPIRE generic names. " ,
errors ,
)
2012-10-19 15:23:34 +02:00
def test_12_service_valid ( self ) :
2020-04-15 01:20:30 +02:00
self . assert_passes_all_gemini2_1_validation (
" gemini2.1/validation/12_Service_Valid.xml "
)
2012-10-19 15:23:34 +02:00
def test_13_dataset_fail_iso19139_schema_2 ( self ) :
# This test Dataset has srv tags and only Service metadata should.
2020-04-15 01:20:30 +02:00
errors = self . get_validation_errors (
validation . ISO19139EdenSchema ,
" gemini2.1/validation/13_Dataset_Invalid_Element_srv.xml " ,
)
2012-10-19 15:23:34 +02:00
assert len ( errors ) > 0
2020-04-15 01:20:30 +02:00
assert_in ( " (gmx.xsd) " , errors )
assert_in (
" Element ' { http://www.isotc211.org/2005/srv}SV_ServiceIdentification ' : This element is not expected. " ,
errors ,
)
2012-10-19 15:23:34 +02:00
def test_schematron_error_extraction ( self ) :
2020-04-15 01:20:30 +02:00
validation_error_xml = """
2012-10-19 15:23:34 +02:00
< root xmlns : svrl = " http://purl.oclc.org/dsdl/svrl " >
< svrl : failed - assert test = " srv:serviceType/*[1] = ' discovery ' or srv:serviceType/*[1] = ' view ' or srv:serviceType/*[1] = ' download ' or srv:serviceType/*[1] = ' transformation ' or srv:serviceType/*[1] = ' invoke ' or srv:serviceType/*[1] = ' other ' " location = " /*[local-name()= ' MD_Metadata ' and namespace-uri()= ' http://www.isotc211.org/2005/gmd ' ]/*[local-name()= ' identificationInfo ' and namespace-uri()= ' http://www.isotc211.org/2005/gmd ' ]/*[local-name()= ' SV_ServiceIdentification ' and namespace-uri()= ' http://www.isotc211.org/2005/srv ' ] " >
< svrl : text >
Service type shall be one of ' discovery ' , ' view ' , ' download ' , ' transformation ' , ' invoke ' or ' other ' following INSPIRE generic names .
< / svrl : text >
< / svrl : failed - assert >
< / root >
2020-04-15 01:20:30 +02:00
"""
2012-10-19 15:23:34 +02:00
failure_xml = etree . fromstring ( validation_error_xml )
fail_element = failure_xml . getchildren ( ) [ 0 ]
2020-04-15 01:20:30 +02:00
details = validation . SchematronValidator . extract_error_details (
fail_element
)
2012-10-19 15:23:34 +02:00
if isinstance ( details , tuple ) :
details = details [ 1 ]
assert_in ( " srv:serviceType/*[1] = ' discovery ' " , details )
assert_in ( " /*[local-name()= ' MD_Metadata ' " , details )
assert_in ( " Service type shall be one of ' discovery ' " , details )
2012-11-19 18:15:16 +01:00
def test_error_line_numbers ( self ) :
2020-04-15 01:20:30 +02:00
file_path = self . _get_file_path ( " iso19139/dataset-invalid.xml " )
2012-11-19 18:15:16 +01:00
xml = etree . parse ( file_path )
2020-04-15 01:20:30 +02:00
is_valid , profile , errors = validation . Validators (
profiles = [ " iso19139 " ]
) . is_valid ( xml )
2012-11-19 18:15:16 +01:00
assert not is_valid
assert len ( errors ) == 2
message , line = errors [ 1 ]
2020-04-15 01:20:30 +02:00
assert " This element is not expected " in message
2012-11-19 18:15:16 +01:00
assert line == 3