def test_conversion(self): """ Check conversion to a PDU produces the correct output """ assoc = A_ASSOCIATE() assoc.application_context_name = "1.2.840.10008.3.1.1.1" assoc.calling_ae_title = 'ECHOSCU' assoc.called_ae_title = 'ANY-SCP' assoc.maximum_length_received = 16382 assoc.implementation_class_uid = '1.2.826.0.1.3680043.9.3811.0.9.0' imp_ver_name = ImplementationVersionNameNotification() imp_ver_name.implementation_version_name = 'PYNETDICOM_090' assoc.user_information.append(imp_ver_name) pc = PresentationContext() pc.context_id = 1 pc.abstract_syntax = '1.2.840.10008.1.1' pc.transfer_syntax = ['1.2.840.10008.1.2'] assoc.presentation_context_definition_list = [pc] pdu = A_ASSOCIATE_RQ() pdu.from_primitive(assoc) data = pdu.encode() ref = b"\x01\x00\x00\x00\x00\xd1\x00\x01\x00\x00\x41\x4e\x59\x2d\x53\x43" \ b"\x50\x20\x20\x20\x20\x20\x20\x20\x20\x20\x45\x43\x48\x4f\x53\x43" \ b"\x55\x20\x20\x20\x20\x20\x20\x20\x20\x20\x00\x00\x00\x00\x00\x00" \ b"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \ b"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x10\x00\x00\x15\x31\x2e" \ b"\x32\x2e\x38\x34\x30\x2e\x31\x30\x30\x30\x38\x2e\x33\x2e\x31\x2e" \ b"\x31\x2e\x31\x20\x00\x00\x2e\x01\x00\x00\x00\x30\x00\x00\x11\x31" \ b"\x2e\x32\x2e\x38\x34\x30\x2e\x31\x30\x30\x30\x38\x2e\x31\x2e\x31" \ b"\x40\x00\x00\x11\x31\x2e\x32\x2e\x38\x34\x30\x2e\x31\x30\x30\x30" \ b"\x38\x2e\x31\x2e\x32\x50\x00\x00\x3e\x51\x00\x00\x04\x00\x00\x3f" \ b"\xfe\x52\x00\x00\x20\x31\x2e\x32\x2e\x38\x32\x36\x2e\x30\x2e\x31" \ b"\x2e\x33\x36\x38\x30\x30\x34\x33\x2e\x39\x2e\x33\x38\x31\x31\x2e" \ b"\x30\x2e\x39\x2e\x30\x55\x00\x00\x0e\x50\x59\x4e\x45\x54\x44\x49" \ b"\x43\x4f\x4d\x5f\x30\x39\x30" assert data == ref
def request_assoc(self, local_ae, peer_ae, max_pdu_size, pcdl, userspdu=None): """Request an Association with a peer Application Entity SCP. Issues an A-ASSOCIATE request primitive to the DICOM UL service provider Requests an association with a remote AE and waits for association response (local AE is acting as an SCU) Parameters ---------- local_ae : dict Contains information about the local AE, keys 'ae_title', 'port', 'address', 'pdv_size', 'propsed_contexts'. peer_ae : dict Contains information about the peer AE, keys 'ae_title', 'port', 'address'. max_pdu_size : int Maximum PDU size in bytes pcdl : list of pynetdicom3.presentation.PresentationContext A list of the proposed Presentation Contexts for the association If local_ae is ApplicationEntity then this is doubled up unnecessarily userpdu : List of UserInformation objects List of items to be added to the requests user information for use in extended negotiation. See PS3.7 Annex D.3.3 Returns ------- bool True if the Association was accepted, False if rejected or aborted """ self.local_ae = local_ae self.local_ae['pdv_size'] = max_pdu_size self.remote_ae = peer_ae self.local_max_pdu = max_pdu_size ## Build an A-ASSOCIATE request primitive # # The following parameters must be set for a request primitive # ApplicationContextName # CallingAETitle # CalledAETitle # UserInformation # Maximum PDV Length (required) # Implementation Identification - Class UID (required) # CallingPresentationAddress # CalledPresentationAddress # PresentationContextDefinitionList assoc_rq = A_ASSOCIATE() assoc_rq.application_context_name = self.application_context_name assoc_rq.calling_ae_title = self.local_ae['ae_title'] assoc_rq.called_ae_title = self.remote_ae['ae_title'] # Build User Information - PS3.7 Annex D.3.3 # # Maximum Length Negotiation (required) max_length = MaximumLengthNegotiation() max_length.maximum_length_received = self.local_ae['pdv_size'] assoc_rq.user_information = [max_length] # Implementation Identification Notification (required) # Class UID (required) implementation_class_uid = ImplementationClassUIDNotification() implementation_class_uid.implementation_class_uid = UID( pynetdicom_implementation_uid) assoc_rq.user_information.append(implementation_class_uid) # Version Name (optional) implementation_version_name = ImplementationVersionNameNotification() implementation_version_name.implementation_version_name = ( pynetdicom_version) assoc_rq.user_information.append(implementation_version_name) # Add the extended negotiation information (optional) if userspdu is not None: assoc_rq.user_information += userspdu assoc_rq.calling_presentation_address = (self.local_ae['address'], self.local_ae['port']) assoc_rq.called_presentation_address = (self.remote_ae['address'], self.remote_ae['port']) assoc_rq.presentation_context_definition_list = pcdl # ## A-ASSOCIATE request primitive is now complete # Send the A-ASSOCIATE request primitive to the peer via the # DICOM UL service LOGGER.info("Requesting Association") self.dul.send_pdu(assoc_rq) ## Receive the response from the peer # This may be an A-ASSOCIATE confirmation primitive or an # A-ABORT or A-P-ABORT request primitive # assoc_rsp = self.dul.receive_pdu(wait=True, timeout=self.acse_timeout) # Association accepted or rejected if isinstance(assoc_rsp, A_ASSOCIATE): # Accepted if assoc_rsp.result == 0x00: # Get maximum pdu length from answer self.peer_max_pdu = assoc_rsp.maximum_length_received self.parent.peer_ae['pdv_size'] = ( assoc_rsp.maximum_length_received) # FIXME self.parent.peer_max_pdu = assoc_rsp.maximum_length_received # Get accepted presentation contexts using the manager self.context_manager.requestor_contexts = pcdl self.context_manager.acceptor_contexts = ( assoc_rsp.presentation_context_definition_results_list) # Once the context manager gets both sets of contexts it # automatically determines which are accepted and refused self.accepted_contexts = self.context_manager.accepted self.rejected_contexts = self.context_manager.rejected return True, assoc_rsp # Rejected elif assoc_rsp.result in [0x01, 0x02]: # 0x01 is rejected (permanent) # 0x02 is rejected (transient) return False, assoc_rsp # Invalid Result value elif assoc_rsp.result is None: return False, assoc_rsp else: LOGGER.error( "ACSE received an invalid result value from " "the peer AE: '%s'", assoc_rsp.result) raise ValueError("ACSE received an invalid result value from " "the peer AE: '{}'".format(assoc_rsp.result)) # Association aborted elif isinstance(assoc_rsp, (A_ABORT, A_P_ABORT)): return False, assoc_rsp elif assoc_rsp is None: return False, assoc_rsp else: raise ValueError("Unexpected response by the peer AE to the " "ACSE association request")
def test_exceptions(self): """ Check incorrect types/values for properties raise exceptions """ assoc = A_ASSOCIATE() # application_context_name with pytest.raises(TypeError): assoc.application_context_name = 10 with pytest.raises(TypeError): assoc.application_context_name = 45.2 with pytest.raises(ValueError): assoc.application_context_name = 'abc' # calling_ae_title with pytest.raises(TypeError): assoc.calling_ae_title = 45.2 with pytest.raises(TypeError): assoc.calling_ae_title = 100 with pytest.raises(ValueError): assoc.calling_ae_title = '' with pytest.raises(ValueError): assoc.calling_ae_title = ' ' # called_ae_title with pytest.raises(TypeError): assoc.called_ae_title = 45.2 with pytest.raises(TypeError): assoc.called_ae_title = 100 with pytest.raises(ValueError): assoc.called_ae_title = '' with pytest.raises(ValueError): assoc.called_ae_title = ' ' # user_information with pytest.raises(TypeError): assoc.user_information = 45.2 # result with pytest.raises(ValueError): assoc.result = -1 with pytest.raises(ValueError): assoc.result = 3 # result_source with pytest.raises(ValueError): assoc.result_source = 0 # result_source with pytest.raises(ValueError): assoc.result_source = 4 # diagnostic with pytest.raises(ValueError): assoc.diagnostic = 0 with pytest.raises(ValueError): assoc.diagnostic = 4 with pytest.raises(ValueError): assoc.diagnostic = 5 with pytest.raises(ValueError): assoc.diagnostic = 6 with pytest.raises(ValueError): assoc.diagnostic = 8 # calling_presentation_addresss with pytest.raises(TypeError): assoc.calling_presentation_address = ['10.40.94.43', 105] with pytest.raises(TypeError): assoc.calling_presentation_address = (105, '10.40.94.43') # called_presentation_addresss with pytest.raises(TypeError): assoc.called_presentation_address = ['10.40.94.43', 105] with pytest.raises(TypeError): assoc.called_presentation_address = (105, '10.40.94.43') # presentation_context_definition_list with pytest.raises(TypeError): assoc.presentation_context_definition_list = 45.2 # presentation_context_definition_results_list with pytest.raises(TypeError): assoc.presentation_context_definition_results_list = 45.2 # implementation_class_uid with pytest.raises(ValueError): x = assoc.implementation_class_uid imp_uid = ImplementationClassUIDNotification() assoc.user_information.append(imp_uid) with pytest.raises(ValueError): x = assoc.implementation_class_uid
def test_assignment(self): """ Check assignment works correctly """ assoc = A_ASSOCIATE() def test_mode(): assoc.mode = "test value" self.assertRaises(AttributeError, test_mode) def test_preq(): assoc.presentation_requirements = "test value2" self.assertRaises(AttributeError, test_preq) def test_sreq(): assoc.session_requirements = "test value3" self.assertRaises(AttributeError, test_sreq) assoc.application_context_name = "1.2.840.10008.3.1.1.1" self.assertTrue( assoc.application_context_name == UID('1.2.840.10008.3.1.1.1')) assoc.application_context_name = b"1.2.840.10008.3.1.1.1" self.assertTrue( assoc.application_context_name == UID('1.2.840.10008.3.1.1.1')) assoc.application_context_name = UID("1.2.840.10008.3.1.1.1") self.assertTrue( assoc.application_context_name == UID('1.2.840.10008.3.1.1.1')) assoc.calling_ae_title = 'ABCD1234ABCD12345' self.assertTrue(assoc.calling_ae_title == b'ABCD1234ABCD1234') assoc.called_ae_title = 'ABCD1234ABCD12345' self.assertTrue(assoc.called_ae_title == b'ABCD1234ABCD1234') self.assertTrue(assoc.responding_ae_title == b'ABCD1234ABCD1234') max_length = MaximumLengthNegotiation() max_length.maximum_length_received = 31222 assoc.user_information.append(max_length) self.assertTrue( assoc.user_information[0].maximum_length_received == 31222) assoc.user_information = ['a', max_length] self.assertEqual(assoc.user_information, [max_length]) assoc.result = 0 self.assertTrue(assoc.result == 0) assoc.result = 1 self.assertTrue(assoc.result == 1) assoc.result = 2 self.assertTrue(assoc.result == 2) assoc.result_source = 1 self.assertTrue(assoc.result_source == 1) assoc.result_source = 2 self.assertTrue(assoc.result_source == 2) assoc.result_source = 3 self.assertTrue(assoc.result_source == 3) assoc.diagnostic = 1 self.assertTrue(assoc.diagnostic == 1) assoc.diagnostic = 2 self.assertTrue(assoc.diagnostic == 2) assoc.diagnostic = 3 self.assertTrue(assoc.diagnostic == 3) assoc.diagnostic = 7 self.assertTrue(assoc.diagnostic == 7) assoc.calling_presentation_address = ('10.40.94.43', 105) self.assertTrue(assoc.calling_presentation_address == ('10.40.94.43', 105)) assoc.called_presentation_address = ('10.40.94.44', 106) self.assertTrue(assoc.called_presentation_address == ('10.40.94.44', 106)) pc = PresentationContext() pc.context_id = 1 assoc.presentation_context_definition_list = [pc] self.assertTrue(assoc.presentation_context_definition_list == [pc]) assoc.presentation_context_definition_list = ['a', pc] self.assertTrue(assoc.presentation_context_definition_list == [pc]) assoc.presentation_context_definition_results_list = [pc] self.assertTrue( assoc.presentation_context_definition_results_list == [pc]) assoc.presentation_context_definition_results_list = ['a', pc] self.assertTrue( assoc.presentation_context_definition_results_list == [pc]) assoc = A_ASSOCIATE() # No maximum_length_received set self.assertEqual(assoc.maximum_length_received, None) # No MaximumLengthNegotiation present assoc.maximum_length_received = 31223 self.assertTrue( assoc.user_information[0].maximum_length_received == 31223) self.assertTrue(assoc.maximum_length_received == 31223) # MaximumLengthNegotiation already present assoc.maximum_length_received = 31224 self.assertTrue(assoc.maximum_length_received == 31224) # No ImplementationClassUIDNegotiation present assoc.implementation_class_uid = '1.1.2.3.4' self.assertTrue(assoc.user_information[1].implementation_class_uid == UID('1.1.2.3.4')) self.assertTrue(assoc.implementation_class_uid == UID('1.1.2.3.4')) # ImplementationClassUIDNegotiation already present assoc.implementation_class_uid = '1.1.2.3.4' self.assertTrue(assoc.implementation_class_uid == UID('1.1.2.3.4'))