# Passerelle - uniform access to data and services # Copyright (C) 2019 Entr'ouvert # # This program is free software: you can redistribute it and/or modify it # under the terms of the GNU Affero General Public License as published # by the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Affero General Public License for more details. # # You should have received a.deepcopy of the GNU Affero General Public License # along with this program. If not, see . import io import logging import os import pytest import xmlschema import tests.utils from passerelle.apps.mdel_ddpacs.models import Demand, Resource from passerelle.utils import json, sftp from passerelle.utils.zip import ZipTemplate, diff_zip def build_response_zip(**kwargs): zip_template = ZipTemplate(os.path.abspath('tests/data/mdel_ddpacs/response_manifest.json'), ctx=kwargs) return zip_template.name, zip_template.render_to_bytes() @pytest.fixture(autouse=True) def resource(db): return tests.utils.setup_access_rights( Resource.objects.create( slug='test', code_insee='66666', recipient_siret='999999', recipient_service='SERVICE', recipient_guichet='GUICHET', ) ) @pytest.fixture def ddpacs_payload(): schema = Resource.get_doc_xml_schema() d = xmlschema.to_dict('tests/data/pacs-doc.xml', schema=schema.xml_schema) return json.flatten({'PACS': d}) def test_create_demand(app, resource, ddpacs_payload, freezer, sftpserver, caplog): # paramiko log socket errors when connection is closed :/ caplog.set_level(logging.WARNING, 'paramiko.transport') freezer.move_to('2019-01-01') # Push new demand payload = { 'display_id': '1-1', } payload.update(ddpacs_payload) assert Demand.objects.count() == 0 assert resource.jobs_set().count() == 0 resp = app.post_json('/mdel-ddpacs/test/create?raise=1', params=payload) assert resp.json['err'] == 0 assert resp.json['status'] == 'pending' assert Demand.objects.count() == 1 assert resource.jobs_set().count() == 1 url = resp.json['url'] zip_url = resp.json['zip_url'] # Check demand status URL status = app.get(url) assert status.json['err'] == 0 assert status.json == resp.json # Check demand document URL zip_document = app.get(zip_url) with io.BytesIO(zip_document.body) as fd: differences = diff_zip('tests/data/mdel_ddpacs_expected.zip', fd) assert not differences, differences # Check job is skipped as no SFTP is configured assert resource.jobs_set().get().after_timestamp is None resource.jobs() assert resource.jobs_set().get().after_timestamp is not None assert resource.jobs_set().exclude(status='completed').count() == 1 with sftpserver.serve_content({'input': {}, 'output': {}}): content = sftpserver.content_provider.content_object resource.outgoing_sftp = sftp.SFTP( 'sftp://john:doe@{server.host}:{server.port}/output/'.format(server=sftpserver) ) resource.save() resource.jobs() assert not content['output'] # Jump over the 6 hour wait time for retry freezer.move_to('2019-01-02') resource.jobs() assert 'A-1-1-depotDossierPACS-1.zip' in content['output'] # Check it's the same document than through the zip_url with open('/tmp/zip.zip', 'wb') as fd: fd.write(content['output']['A-1-1-depotDossierPACS-1.zip']) with io.BytesIO(content['output']['A-1-1-depotDossierPACS-1.zip']) as fd: differences = diff_zip('tests/data/mdel_ddpacs_expected.zip', fd) assert not differences, differences # Act as if zip was consumed content['output'] = {} # Jump over the 6 hour wait time for retry freezer.move_to('2019-01-03') resource.jobs() assert not content['output'] assert resource.jobs_set().exclude(status='completed').count() == 0 # Check response resource.hourly() resource.incoming_sftp = sftp.SFTP( 'sftp://john:doe@{server.host}:{server.port}/input/'.format(server=sftpserver) ) resource.save() response_name, response_content = build_response_zip( reference='A-1-1', flow_type='depotDossierPACS', step=1, old_step=1, etat=100, commentaire='coucou', ) content['input'][response_name] = response_content resource.hourly() assert resource.demand_set.get().status == 'closed' assert response_name not in content['input'] response_name, response_content = build_response_zip( reference='A-1-1', flow_type='depotDossierPACS', step=1, old_step=1, etat=1, commentaire='coucou' ) content['input'][response_name] = response_content resource.hourly() assert 'unexpected file "A-1-1-depotDossierPACS-1.zip"' in caplog.messages[-1] assert 'step 1 is inferior' in caplog.messages[-1] resource.check_status() def test_create_demand_double(app, resource, ddpacs_payload, freezer, sftpserver, caplog): # paramiko log socket errors when connection is closed :/ caplog.set_level(logging.CRITICAL, 'paramiko.transport') freezer.move_to('2019-01-01') # Push new demand payload = {'display_id': '1-1', 'PACS/convention/conventionType/aideMaterielMontant': 'None'} ddpacs_payload.update(payload) assert Demand.objects.count() == 0 assert resource.jobs_set().count() == 0 resp = app.post_json('/mdel-ddpacs/test/create?raise=1', params=ddpacs_payload) assert resp.json['err'] == 0 assert resp.json['status'] == 'pending' assert Demand.objects.count() == 1 assert resource.jobs_set().count() == 1