def test_produces_sla_given_failure_with_conflicting_acks_and_duplicate_ehrs(): failed_acknowledgement_datetime = a_datetime(year=2020, month=6, day=1, hour=13, minute=52, second=0) conversation = Gp2gpConversation( messages=test_cases. integration_failed_with_conflicting_acks_and_duplicate_ehrs( request_completed_time=a_datetime(year=2020, month=6, day=1, hour=12, minute=42, second=0), ehr_acknowledge_time=failed_acknowledgement_datetime, ), probe=mock_gp2gp_conversation_observability_probe, ) mock_lookup = Mock() transfer_service = TransferService( message_stream=[], cutoff=timedelta(days=14), observability_probe=mock_transfer_observability_probe, ) actual = transfer_service.derive_transfer(conversation, mock_lookup) expected_sla_duration = timedelta(hours=1, minutes=10) assert actual.sla_duration == expected_sla_duration assert actual.date_completed == failed_acknowledgement_datetime
def test_returns_datetimes_between_start_and_end_datetime(): start_datetime = a_datetime(year=2021, month=2, day=1, hour=0, minute=0, second=0) end_datetime = a_datetime(year=2021, month=2, day=3, hour=0, minute=0, second=0) actual = convert_date_range_to_dates(start_datetime, end_datetime) expected = [ datetime(year=2021, month=2, day=1, hour=0, minute=0, second=0, tzinfo=UTC), datetime(year=2021, month=2, day=2, hour=0, minute=0, second=0, tzinfo=UTC), ] assert actual == expected
def test_produces_sla_of_successful_conversation(): conversation = build_mock_gp2gp_conversation( request_completed_time=a_datetime(year=2020, month=6, day=1, hour=12, minute=42, second=0), final_acknowledgement_time=a_datetime(year=2020, month=6, day=1, hour=13, minute=52, second=0), ) mock_lookup = Mock() transfer_service = TransferService( message_stream=[], cutoff=timedelta(days=14), observability_probe=mock_transfer_observability_probe, ) actual = transfer_service.derive_transfer(conversation, mock_lookup) expected_sla_duration = timedelta(hours=1, minutes=10) assert actual.sla_duration == expected_sla_duration
def ehr_integration_failed(**kwargs) -> List[Message]: """ This scenario is an example of a GP2GP transfer that failed to integrate. """ ehr_ack_time = kwargs.get("ehr_acknowledge_time", a_datetime()) req_complete_time = kwargs.get("request_completed_time", a_datetime()) ehr_ack_error = kwargs.get("error_code", 28) conversation_id = a_string() ehr_guid = a_string() return (GP2GPTestCase(conversation_id=conversation_id).with_request( ).with_sender_acknowledgement(message_ref=conversation_id).with_core_ehr( guid=ehr_guid, time=req_complete_time).with_requester_acknowledgement( time=ehr_ack_time, message_ref=ehr_guid, error_code=ehr_ack_error).build())
def build_mock_gp2gp_conversation(**kwargs): conversation_id = kwargs.get("conversation_id", a_string()) final_ack_time = kwargs.get("final_acknowledgement_time", a_datetime()) req_completed_time = kwargs.get("request_completed_time", a_datetime()) sending_practice_asid = kwargs.get("sending_practice_asid", a_string()) requesting_practice_asid = kwargs.get("requesting_practice_asid", a_string()) conversation = Mock() conversation.conversation_id.return_value = conversation_id conversation.effective_final_acknowledgement_time.return_value = final_ack_time conversation.effective_request_completed_time.return_value = req_completed_time conversation.sending_practice_asid.return_value = sending_practice_asid conversation.requesting_practice_asid.return_value = requesting_practice_asid return conversation
def test_produces_last_sender_message_timestamp_given_request_acked_successfully( ): request_acknowledged_date = a_datetime(year=2020, month=6, day=1, hour=12, minute=42, second=0) conversation = Gp2gpConversation( messages=test_cases.request_acknowledged_successfully( sender_ack_time=request_acknowledged_date), probe=mock_gp2gp_conversation_observability_probe, ) mock_lookup = Mock() transfer_service = TransferService( message_stream=[], cutoff=timedelta(days=14), observability_probe=mock_transfer_observability_probe, ) actual = transfer_service.derive_transfer(conversation, mock_lookup) expected = request_acknowledged_date assert actual.last_sender_message_timestamp == expected
def test_produces_last_sender_message_timestamp_from_request_completed_before_integration_only( ): request_completed_date = a_datetime(year=2020, month=6, day=1, hour=12, minute=42, second=0) messages = test_cases.ehr_integrated_with_duplicate_having_second_sender_ack_after_integration( request_completed_time=request_completed_date) conversation = Gp2gpConversation( messages=messages, probe=mock_gp2gp_conversation_observability_probe, ) mock_lookup = Mock() transfer_service = TransferService( message_stream=[], cutoff=timedelta(days=14), observability_probe=mock_transfer_observability_probe, ) actual = transfer_service.derive_transfer(conversation, mock_lookup) expected_last_sender_message_timestamp = request_completed_date assert actual.last_sender_message_timestamp == expected_last_sender_message_timestamp
def test_produces_last_sender_message_timestamp_given_an_integrated_ontime_transfer_with_copcs( ): request_completed_date = a_datetime(year=2020, month=6, day=1, hour=12, minute=42, second=0) conversation = Gp2gpConversation( messages=test_cases.successful_integration_with_copc_fragments( request_completed_time=request_completed_date), probe=mock_gp2gp_conversation_observability_probe, ) mock_lookup = Mock() transfer_service = TransferService( message_stream=[], cutoff=timedelta(days=14), observability_probe=mock_transfer_observability_probe, ) actual = transfer_service.derive_transfer(conversation, mock_lookup) expected_last_sender_message_timestamp = request_completed_date assert actual.last_sender_message_timestamp == expected_last_sender_message_timestamp
def successful_integration_with_copc_fragments(**kwargs) -> List[Message]: """ A GP2GP transfer where the record was large enough (or had enough attachments) to necessitate using COPC messages to transmit the data in multiple chunks. In this instance, all transmitted COPC messages have been acknowledged by the requester, and the record has been integrated. """ req_complete_time = kwargs.get("request_completed_time", a_datetime()) ehr_ack_time = kwargs.get("ehr_acknowledge_time", req_complete_time + timedelta(days=1)) conversation_id = a_string() ehr_guid = a_string() fragment1_guid = a_string() fragment2_guid = a_string() fragment3_guid = a_string() return (GP2GPTestCase(conversation_id=conversation_id).with_request( ).with_sender_acknowledgement(message_ref=conversation_id).with_core_ehr( guid=ehr_guid, time=req_complete_time).with_copc_fragment_continue( ).with_copc_fragment(guid=fragment1_guid).with_copc_fragment( guid=fragment2_guid).with_requester_acknowledgement( message_ref=fragment1_guid).with_requester_acknowledgement( message_ref=fragment2_guid).with_copc_fragment( guid=fragment3_guid).with_requester_acknowledgement( message_ref=fragment3_guid). with_requester_acknowledgement(message_ref=ehr_guid, time=ehr_ack_time).build())
def build_transfer(**kwargs) -> Transfer: return Transfer( conversation_id=kwargs.get("conversation_id", a_string(36)), sla_duration=kwargs.get("sla_duration", a_duration()), requesting_practice=kwargs.get( "requesting_practice", Practice(asid=a_string(12), supplier=a_string(12), ods_code=a_string(4)), ), sending_practice=kwargs.get( "sending_practice", Practice(asid=a_string(12), supplier=a_string(12), ods_code=a_string(4)), ), sender_error_codes=kwargs.get("sender_error_codes", []), final_error_codes=kwargs.get("final_error_codes", []), intermediate_error_codes=kwargs.get("intermediate_error_codes", []), outcome=kwargs.get( "outcome", TransferOutcome(status=TransferStatus.INTEGRATED_ON_TIME, failure_reason=None), ), date_requested=kwargs.get("date_requested", a_datetime()), date_completed=kwargs.get("date_completed", None), last_sender_message_timestamp=None, )
def ehr_integrated_with_duplicate_having_second_sender_ack_after_integration( **kwargs, ) -> List[Message]: """ While normally the "request completed" message (aka "core ehr" message) is only transmitted once, sometimes there are duplicate copies sent by the sending practice. In this instance, the sender first sent two copies and the requester reported via negative ack that the first was a duplicate and that the second was integrated. After this the sender sent a third copy, which was ignored. """ req_complete_time = kwargs.get("request_completed_time", a_datetime()) req_complete_time_duplicate = req_complete_time - timedelta(hours=1) ehr_ack_time = kwargs.get("ehr_acknowledge_time", req_complete_time) sender_ack_time = ehr_ack_time - timedelta(hours=1) request_complete_time_after_integration = ehr_ack_time + timedelta(hours=1) conversation_id = a_string() ehr_guid = a_string() duplicate_ehr_guid = a_string() return (GP2GPTestCase(conversation_id=conversation_id).with_request( ).with_sender_acknowledgement( message_ref=conversation_id, time=sender_ack_time).with_core_ehr( guid=duplicate_ehr_guid, time=req_complete_time_duplicate).with_core_ehr( guid=ehr_guid, time=req_complete_time).with_requester_acknowledgement( message_ref=duplicate_ehr_guid, error_code=DUPLICATE_EHR_ERROR). with_requester_acknowledgement( time=ehr_ack_time, message_ref=ehr_guid).with_core_ehr( guid=duplicate_ehr_guid, time=request_complete_time_after_integration).build())
def test_produces_last_sender_message_timestamp_given_copc_fragment_failure(): copc_fragment_time = a_datetime(year=2020, month=6, day=1, hour=12, minute=42, second=0) conversation = Gp2gpConversation( messages=test_cases.copc_fragment_failure( copc_fragment_time=copc_fragment_time), probe=mock_gp2gp_conversation_observability_probe, ) mock_lookup = Mock() transfer_service = TransferService( message_stream=[], cutoff=timedelta(days=14), observability_probe=mock_transfer_observability_probe, ) actual = transfer_service.derive_transfer(conversation, mock_lookup) expected_last_sender_message_timestamp = copc_fragment_time assert actual.last_sender_message_timestamp == expected_last_sender_message_timestamp
def test_logs_negative_sla_warning(): conversation_id = a_string() mock_probe = Mock() conversation = build_mock_gp2gp_conversation( conversation_id=conversation_id, final_acknowledgement_time=a_datetime(year=2021, month=12, day=1), request_completed_time=a_datetime(year=2021, month=12, day=2), ) mock_lookup = Mock() transfer_service = TransferService(message_stream=[], cutoff=timedelta(days=14), observability_probe=mock_probe) transfer_service.derive_transfer(conversation, mock_lookup) mock_probe.record_negative_sla.assert_called_once_with(conversation)
def test_exposes_date_delivered(): date_delivered = a_datetime() status_timestamp_header = date_delivered.strftime("%Y%m%d%H%M%S") client_message = mock_client_message(mex_headers=build_mex_headers( status_timestamp=status_timestamp_header)) message = MeshMessage(client_message) assert message.date_delivered == date_delivered
def test_negative_sla_duration_clamped_to_zero(): conversation = build_mock_gp2gp_conversation( request_completed_time=a_datetime(year=2021, month=1, day=5), final_acknowledgement_time=a_datetime(year=2021, month=1, day=4), ) expected_sla_duration = timedelta(0) mock_lookup = Mock() transfer_service = TransferService( message_stream=[], cutoff=timedelta(days=14), observability_probe=mock_transfer_observability_probe, ) actual = transfer_service.derive_transfer(conversation, mock_lookup) assert actual.sla_duration == expected_sla_duration
def mock_mesh_message(**kwargs): message = MagicMock() message.id = kwargs.get("message_id", a_string()) message.file_name = kwargs.get("file_name", a_string()) message.sender = kwargs.get("sender", a_string()) message.recipient = kwargs.get("recipient", a_string()) message.validate.side_effect = kwargs.get("validation_error", None) message.acknowledge.side_effect = kwargs.get("acknowledge_error", None) message.date_delivered = kwargs.get("date_delivered", a_datetime()) return message
def test_extracts_date_requested_from_request_started_message(): date_requested = a_datetime() gp2gp_messages: List[Message] = test_cases.request_made(request_sent_date=date_requested) conversation = Gp2gpConversation(gp2gp_messages, mock_gp2gp_conversation_observability_probe) actual = conversation.date_requested() assert actual == date_requested
def request_acknowledged_successfully(**kwargs) -> List[Message]: """ In this example, the sender responded to the initial request with a successful ack, but is yet to send the core EHR. """ conversation_id = a_string() return (GP2GPTestCase(conversation_id=conversation_id).with_request(). with_sender_acknowledgement( message_ref=conversation_id, time=kwargs.get("sender_ack_time", a_datetime()), ).build())
def test_convert_to_datetimes_string_returns_datetimes_string_given_datetimes( ): some_datetime = a_datetime(year=2021, month=11, day=13, hour=2, minute=0, second=0) some_other_datetime = a_datetime(year=2022, month=10, day=13, hour=2, minute=0, second=0) actual = convert_to_datetimes_string([some_datetime, some_other_datetime]) expected = ["2021-11-13T02:00:00+00:00", "2022-10-13T02:00:00+00:00"] assert actual == expected
def _concluded_with_conflicting_acks(**kwargs) -> List[Message]: conversation_id = a_string() default_codes_and_times = [(None, a_datetime()), (DUPLICATE_EHR_ERROR, a_datetime())] codes_and_times = kwargs.get("codes_and_times", default_codes_and_times) req_complete_time = kwargs.get("request_completed_time", a_datetime()) ehr_guid = a_string() test_case = (GP2GPTestCase(conversation_id=conversation_id).with_request( ).with_sender_acknowledgement(message_ref=conversation_id).with_core_ehr( guid=ehr_guid, time=req_complete_time)) for code, ack_time in codes_and_times: test_case = test_case.with_requester_acknowledgement( message_ref=ehr_guid, error_code=code, time=ack_time, ) return test_case.build()
def ehr_integrated_after_duplicate(**kwargs) -> List[Message]: """ While normally the "request completed" message (aka "core ehr" message) is only transmitted once, sometimes there are duplicate copies sent by the sending practice. In this instance, the requester reported via negative ack that the second was a duplicate, then successfully integrated the first copy. """ ehr_ack_time = kwargs.get("ehr_acknowledge_time", a_datetime()) req_complete_time = kwargs.get("request_completed_time", a_datetime()) conversation_id = a_string() ehr_guid = a_string() duplicate_ehr_guid = a_string() return (GP2GPTestCase(conversation_id=conversation_id).with_request( ).with_sender_acknowledgement(message_ref=conversation_id).with_core_ehr( guid=ehr_guid, time=req_complete_time).with_core_ehr( guid=duplicate_ehr_guid).with_requester_acknowledgement( message_ref=duplicate_ehr_guid, error_code=DUPLICATE_EHR_ERROR).with_requester_acknowledgement( time=ehr_ack_time, message_ref=ehr_guid).build())
def build_message(**kwargs): return Message( time=kwargs.get("time", a_datetime()), conversation_id=kwargs.get("conversation_id", a_string(36)), guid=kwargs.get("guid", a_string(36)), interaction_id=kwargs.get("interaction_id", a_string(17)), from_party_ods=kwargs.get("from_party_ods", a_string(6)), to_party_ods=kwargs.get("to_party_ods", a_string(6)), message_ref=kwargs.get("message_ref", None), error_code=kwargs.get("error_code", None), )
def core_ehr_sent(**kwargs) -> List[Message]: """ In this example, the sender has returned an EHR, but the requester is yet to acknowledge. """ conversation_id = a_string() req_complete_time = kwargs.get("request_completed_time", a_datetime()) return (GP2GPTestCase(conversation_id=conversation_id).with_request( ).with_sender_acknowledgement( message_ref=conversation_id, time=req_complete_time - timedelta(hours=1)).with_core_ehr(time=req_complete_time).build())
def ehr_suppressed_with_conflicting_duplicate_and_conflicting_error_ack( **kwargs) -> List[Message]: """ Usually a requesting system acknowledges the GP2GP request completed message (aka core EHR) once. However, in this case there are three conflicting acknowledgements to the Core EHR message, with the requester reporting an error code, a duplicate, and a suppressed record. """ request_completed_time = kwargs.setdefault("request_completed_time", a_datetime()) ehr_ack_time = kwargs.get("ehr_acknowledge_time", request_completed_time + timedelta(hours=4)) return _concluded_with_conflicting_acks( **kwargs, codes_and_times=[ (11, a_datetime()), (DUPLICATE_EHR_ERROR, a_datetime()), (SUPPRESSED_EHR_ERROR, ehr_ack_time), ], )
def first_ehr_integrated_after_second_ehr_failed(**kwargs) -> List[Message]: """ While normally the "request completed" message (aka "core ehr" message) is only transmitted once, sometimes there are duplicate copies sent by the sending practice. In this instance, the requester sent a negative acknowledgment in response to the second copy, then integrated the first. """ ehr_ack_time = kwargs.get("ehr_acknowledge_time", a_datetime()) req_complete_time = kwargs.get("request_completed_time", a_datetime()) ehr_ack_error = kwargs.get("error_code", 11) conversation_id = a_string() first_ehr_guid = a_string() second_ehr_guid = a_string() return (GP2GPTestCase(conversation_id=conversation_id).with_request( ).with_sender_acknowledgement(message_ref=conversation_id).with_core_ehr( guid=first_ehr_guid, time=req_complete_time).with_core_ehr( guid=second_ehr_guid).with_requester_acknowledgement( message_ref=second_ehr_guid, error_code=ehr_ack_error).with_requester_acknowledgement( message_ref=first_ehr_guid, time=ehr_ack_time).build())
def test_returns_correct_time_when_conversation_has_concluded(test_case): acknowledgement_time = a_datetime() gp2gp_messages: List[Message] = test_case( ehr_acknowledge_time=acknowledgement_time, ) conversation = Gp2gpConversation( gp2gp_messages, mock_gp2gp_conversation_observability_probe) expected = acknowledgement_time actual = conversation.effective_final_acknowledgement_time() assert actual == expected
def test_returns_correct_time_when_conversation_has_concluded(test_case): request_completed_time = a_datetime() gp2gp_messages: List[Message] = test_case( request_completed_time=request_completed_time) conversation = Gp2gpConversation( gp2gp_messages, mock_gp2gp_conversation_observability_probe) expected = request_completed_time actual = conversation.effective_request_completed_time() assert actual == expected
def test_convert_to_datetime_string_returns_datetime_string_given_a_datetime(): some_datetime = a_datetime(year=2021, month=11, day=13, hour=2, minute=0, second=0) actual = convert_to_datetime_string(some_datetime) expected = "2021-11-13T02:00:00+00:00" assert actual == expected
def test_extracts_date_requested_from_request_started_message(): date_requested = a_datetime() conversations = [ build_parsed_conversation( request_started=build_message(time=date_requested), request_completed=build_message(), request_completed_ack=build_message(), ) ] actual = derive_transfers(conversations) _assert_attributes("date_requested", actual, [date_requested])
def test_resolver_returns_correct_asid_lookup_uri_given_date_anchor(): asid_lookup_bucket = a_string() date_anchor = a_datetime() year = date_anchor.year month = date_anchor.month uri_resolver = OdsDownloaderS3UriResolver( asid_lookup_bucket=asid_lookup_bucket, ods_metadata_bucket=a_string()) actual = uri_resolver.asid_lookup(date_anchor) expected = f"s3://{asid_lookup_bucket}/{year}/{month}/asidLookup.csv.gz" assert actual == expected