def test_validate_metadata_datacite_bad_request(requests_mock): """Test validate_metadata. Function should raise exception with correct error message if Metax fails to generate datacite for dataset, for example when `publisher` attribute is missing. :param requests_mock: Mocker object :returns: ``None`` """ dataset_file = copy.deepcopy(TXT_FILE) tests.utils.add_metax_dataset(requests_mock, files=[dataset_file]) # Mock datacite request response. Mocked response has status code 400, and # response body contains error information. requests_mock.get(tests.conftest.METAX_URL + '/datasets/dataset_identifier?' 'dataset_format=datacite', json={"detail": "Bad request"}, status_code=400) # Try to validate invalid dataset expected_error = "Datacite generation failed: Bad request" with pytest.raises(InvalidDatasetMetadataError, match=expected_error): validate_metadata('dataset_identifier', tests.conftest.UNIT_TEST_CONFIG_FILE)
def test_validate_metadata_invalid_datacite(requests_mock): """Test validate_metadata. Function should raise exception with correct error message for invalid datacite where required attribute identifier is missing. :param requests_mock: Mocker object :returns: ``None`` """ dataset_file = copy.deepcopy(TXT_FILE) tests.utils.add_metax_dataset(requests_mock, files=[dataset_file]) requests_mock.get( "https://metaksi/rest/v1/datasets/dataset_identifier?" "dataset_format=datacite", content=get_invalid_datacite()) # Try to validate invalid dataset with pytest.raises(InvalidDatasetMetadataError) as exception_info: validate_metadata('dataset_identifier', tests.conftest.UNIT_TEST_CONFIG_FILE) # Check error message assert str(exception_info.value).startswith( "Datacite metadata is invalid: Element " "'{http://datacite.org/schema/kernel-4}resource': Missing child " "element(s).")
def validate_dataset_metadata(dataset_id): """Validate dataset metadata. :returns: HTTP Response """ # Validate dataset metadata try: validate_metadata( dataset_id, app.config.get('SIPTOOLS_RESEARCH_CONF'), dummy_doi="true" ) except InvalidDatasetError as exc: is_valid = False error = "Metadata did not pass validation" detailed_error = str(exc) else: is_valid = True error = '' detailed_error = '' response = jsonify({'dataset_id': dataset_id, 'is_valid': is_valid, 'error': error, 'detailed_error': detailed_error}) response.status_code = 200 return response
def test_validate_metadata_missing_file(requests_mock): """Test validate_metadata with an empty dataset. Function should raise InvalidDatasetMetadataError for datasets, which do not contain any files. :param requests_mock: Mocker object :returns: ``None`` """ tests.utils.add_metax_dataset(requests_mock) expected_error = "Dataset must contain at least one file" with pytest.raises(InvalidDatasetMetadataError, match=expected_error): validate_metadata('dataset_identifier', tests.conftest.UNIT_TEST_CONFIG_FILE)
def test_validate_metadata_http_error_raised(requests_mock): """Test validate_metadata. Function should raise HTTPError if Metax fails. :param requests_mock: Mocker object :returns: ``None`` """ tests.utils.add_metax_dataset(requests_mock) requests_mock.get( 'https://metaksi/rest/v1/datasets/dataset_identifier/files', status_code=500, reason='Something not to be shown to user') expected_error = '500 Server Error: Something not to be shown to user' with pytest.raises(HTTPError, match=expected_error): validate_metadata('dataset_identifier', tests.conftest.UNIT_TEST_CONFIG_FILE)
def test_validate_metadata_invalid_contract_metadata(requests_mock): """Test validate_metadata. Function raises exception with correct error message for invalid dataset. :param requests_mock: Mocker object :returns: ``None`` """ invalid_contract = copy.deepcopy(BASE_CONTRACT) del invalid_contract['contract_json']['organization']['name'] tests.utils.add_metax_dataset(requests_mock, contract=invalid_contract) # Try to validate invalid dataset expected_error = ("'name' is a required property\n\n" "Failed validating 'required' in schema") with pytest.raises(InvalidContractMetadataError, match=expected_error): validate_metadata('dataset_identifier', tests.conftest.UNIT_TEST_CONFIG_FILE)
def test_validate_metadata_invalid(requests_mock): """Test validate_metadata. Function should raise exception with correct error message for invalid dataset. :returns: ``None`` """ dataset = copy.deepcopy(BASE_DATASET) del dataset['contract'] requests_mock.get("https://metaksi/rest/v1/datasets/dataset_identifier", json=dataset) # Try to validate invalid dataset expected_error = "'contract' is a required property" with pytest.raises(InvalidDatasetMetadataError, match=expected_error): validate_metadata('dataset_identifier', tests.conftest.UNIT_TEST_CONFIG_FILE)
def test_validate_metadata_invalid_file_path(requests_mock): """Test validate_metadata. Function should raise exception if some of the file paths point outside SIP. :param requests_mock: Mocker object :returns: ``None`` """ invalid_file = copy.deepcopy(TXT_FILE) invalid_file['file_path'] = "../../file_in_invalid_path" tests.utils.add_metax_dataset(requests_mock, files=[invalid_file]) # Try to validate invalid dataset expected_error = ("The file path of file pid:urn:identifier is invalid: " "../../file_in_invalid_path") with pytest.raises(InvalidFileMetadataError, match=expected_error): validate_metadata('dataset_identifier', tests.conftest.UNIT_TEST_CONFIG_FILE)
def test_validate_metadata_invalid_directory_metadata(requests_mock): """Test validate_metadata wihth invalid directory metadata. Function should raise exception if directory metadata is not valid (directory_path attribute is missing). :param requests_mock: Mocker object :returns: ``None`` """ file_metadata = copy.deepcopy(TXT_FILE) tests.utils.add_metax_dataset(requests_mock, files=[file_metadata]) requests_mock.get("https://metaksi/rest/v1/directories/pid:urn:dir:wf1", json={"identifier": "pid:urn:dir:wf1"}) # Try to validate invalid dataset expected_error = ("Validation error in metadata of pid:urn:dir:wf1: " "'directory_path' is a required property") with pytest.raises(InvalidDatasetMetadataError, match=expected_error): validate_metadata('dataset_identifier', tests.conftest.UNIT_TEST_CONFIG_FILE)
def test_validate_metadata_corrupted_datacite(requests_mock): """Test validate_metadata. Function should raise exception if datacite XML is corrupted. :param requests_mock: Mocker object :returns: ``None`` """ dataset_file = copy.deepcopy(TXT_FILE) tests.utils.add_metax_dataset(requests_mock, files=[dataset_file]) requests_mock.get( "https://metaksi/rest/v1/datasets/dataset_identifier?" "dataset_format=datacite", text="<resource\n") # Try to validate invalid dataset expected_error \ = "Couldn't find end of Start Tag resource line 1, line 2, column 1" with pytest.raises(Exception, match=expected_error): validate_metadata('dataset_identifier', tests.conftest.UNIT_TEST_CONFIG_FILE)
def test_validate_invalid_file_type(file_characteristics, version_info, requests_mock): """Test validate_metadata. Function should raise exception with correct error message for unsupported file type. :param file_characteristics: file characteristics dict in file metadata :param version_info: expected version information in exception message :param requests_mock: Mocker object :returns: ``None`` """ unsupported_file = copy.deepcopy(BASE_FILE) unsupported_file['file_characteristics'] = file_characteristics tests.utils.add_metax_dataset(requests_mock, files=[unsupported_file]) # Try to validate dataset with a file that has an unsupported file_format expected_error = ( "Validation error in file path/to/file: Incorrect file format: " "application/unsupported{}".format(version_info)) with pytest.raises(InvalidFileMetadataError, match=expected_error): validate_metadata('dataset_identifier', tests.conftest.UNIT_TEST_CONFIG_FILE)
def test_validate_metadata(requests_mock): """Test validate_metadata. Function should return ``True`` for a valid dataset. :param requests_mock: Mocker object :returns: ``None`` """ files = [copy.deepcopy(TXT_FILE), copy.deepcopy(TXT_FILE)] files[0]['identifier'] = "pid:urn:1" files[1]['identifier'] = "pid:urn:2" tests.utils.add_metax_dataset(requests_mock, files=files) assert validate_metadata('dataset_identifier', tests.conftest.UNIT_TEST_CONFIG_FILE)
def test_validate_metadata_languages(translations, expectation, requests_mock): """Test validate_metadata. Function should raise exception when one of the localized fields has invalid values. :returns: ``None`` """ dataset = copy.deepcopy(BASE_DATASET) dataset_file = copy.deepcopy(TXT_FILE) dataset['research_dataset']['provenance'][0]['description'] = translations tests.utils.add_metax_dataset(requests_mock, dataset=dataset, files=[dataset_file]) with expectation: assert validate_metadata('dataset_identifier', tests.conftest.UNIT_TEST_CONFIG_FILE)
def test_validate_metadata_multiple_formats(requests_mock, file_format, stream_type, xml): """Test validate_metadata. Function validates different types of technical metadata. :param requests_mock: Mocker object :param file_format: file mimetype :param stream_type: stream type contained within the file :param xml: techincal metada as xml object :returns: ``None`` """ file_metadata = copy.deepcopy(BASE_FILE) file_metadata.update({ "file_characteristics": { "file_format": file_format }, "file_characteristics_extension": { "streams": { 0: { "mimetype": file_format, "stream_type": stream_type } } } }) tests.utils.add_metax_dataset(requests_mock, files=[file_metadata]) requests_mock.get("https://metaksi/rest/v1/files/{}/xml".format( file_metadata['identifier']), json=[METS_NS]) requests_mock.get("https://metaksi/rest/v1/files/{}/xml?" "namespace={}".format(file_metadata['identifier'], METS_NS), content=six.binary_type(lxml.etree.tostring(xml))) assert validate_metadata('dataset_identifier', tests.conftest.UNIT_TEST_CONFIG_FILE)