# HG changeset patch # User Sebastien Jodogne # Date 1550994602 -3600 # Node ID 00e5aeea33dd57e3246b12206996d932437383ac # Parent 70fba41776beffe0299c72973f076ffb8b481216 test_bitbucket_issue_131 diff -r 70fba41776be -r 00e5aeea33dd .hgignore --- a/.hgignore Thu Feb 21 10:31:54 2019 +0100 +++ b/.hgignore Sun Feb 24 08:50:02 2019 +0100 @@ -6,4 +6,5 @@ PerfsDb/Storages/ PerfsDb/ConfigFiles/ PerfsDb/Results/ -.vscode/ \ No newline at end of file +.vscode/ +*~ diff -r 70fba41776be -r 00e5aeea33dd Database/PatientIdsCollision/Generate.sh --- a/Database/PatientIdsCollision/Generate.sh Thu Feb 21 10:31:54 2019 +0100 +++ b/Database/PatientIdsCollision/Generate.sh Sun Feb 24 08:50:02 2019 +0100 @@ -6,3 +6,6 @@ do dump2dcm +Ug --write-xfer-little Image$i.dump Image$i.dcm done + +dump2dcm +Ug --write-xfer-little Issue131-a.dump Issue131-a.dcm +dump2dcm +Ug --write-xfer-little Issue131-b.dump Issue131-b.dcm diff -r 70fba41776be -r 00e5aeea33dd Database/PatientIdsCollision/Issue131-a.dcm Binary file Database/PatientIdsCollision/Issue131-a.dcm has changed diff -r 70fba41776be -r 00e5aeea33dd Database/PatientIdsCollision/Issue131-a.dump --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Database/PatientIdsCollision/Issue131-a.dump Sun Feb 24 08:50:02 2019 +0100 @@ -0,0 +1,5 @@ +(0008,0016) UI 1.2.840.10008.5.1.4.1.1.4 +(0010,0020) LO A # Patient ID +(0010,0010) PN HELLO^A # Patient Name +(0008,1030) LO SERIES^A # Study description +(0020,000D) UI 2.25.123 # Study Instance UID diff -r 70fba41776be -r 00e5aeea33dd Database/PatientIdsCollision/Issue131-b.dcm Binary file Database/PatientIdsCollision/Issue131-b.dcm has changed diff -r 70fba41776be -r 00e5aeea33dd Database/PatientIdsCollision/Issue131-b.dump --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Database/PatientIdsCollision/Issue131-b.dump Sun Feb 24 08:50:02 2019 +0100 @@ -0,0 +1,5 @@ +(0008,0016) UI 1.2.840.10008.5.1.4.1.1.4 +(0010,0020) LO B # Patient ID +(0010,0010) PN HELLO^B # Patient Name +(0008,1030) LO SERIES^B # Study description +(0020,000D) UI 2.25.123 # Study Instance UID diff -r 70fba41776be -r 00e5aeea33dd Tests/Tests.py --- a/Tests/Tests.py Thu Feb 21 10:31:54 2019 +0100 +++ b/Tests/Tests.py Sun Feb 24 08:50:02 2019 +0100 @@ -4520,3 +4520,76 @@ rows = re.findall('\(0028,0010\) US ([0-9]+)', i) self.assertEqual(1, len(rows)) self.assertEqual('512', rows[0]) + + + + def test_bitbucket_issue_131(self): + # "Orthanc PACS silently fails to C-MOVE due to duplicate + # StudyInstanceUID in it's database." + # https://bitbucket.org/sjodogne/orthanc/issues/131/orthanc-pacs-silently-fails-to-c-move-due + + # Insert 2 instances, with the same StudyInstanceUID, but with + # different patient IDs. Orthanc will create 2 distincts + # patients, and the hierarchy of resources above the two + # instances will be fully disjoint. + UploadInstance(_REMOTE, 'PatientIdsCollision/Issue131-a.dcm') + UploadInstance(_REMOTE, 'PatientIdsCollision/Issue131-b.dcm') + + self.assertEqual(2, len(DoGet(_REMOTE, '/patients'))) + self.assertEqual(2, len(DoGet(_REMOTE, '/studies'))) + + a = DoPost(_REMOTE, '/modalities/self/query', { + 'Level' : 'Study', + 'Query' : {"PatientID": "A" }})['ID'] + + # 1 study is matched + self.assertEqual(1, len(DoGet(_REMOTE, '/queries/%s/answers' % a))) + + self.assertEqual(0, len(DoGet(_LOCAL, '/instances'))) + self.assertTrue(MonitorJob(_REMOTE, lambda: DoPost + (_REMOTE, '/queries/%s/retrieve' % a, + '{"TargetAet":"ORTHANCTEST","Synchronous":false}'))) + + # The two studies are matched, as we made the request at the + # Study level, thus the shared StudyInstanceUID is used as the key + self.assertEqual(2, len(DoGet(_LOCAL, '/instances'))) + + + # Match the 2 studies + a = DoPost(_REMOTE, '/modalities/self/query', { + 'Level' : 'Study', + 'Query' : {"StudyInstanceUID": "2.25.123" }})['ID'] + self.assertEqual(2, len(DoGet(_REMOTE, '/queries/%s/answers' % a))) + DropOrthanc(_LOCAL) + self.assertEqual(0, len(DoGet(_LOCAL, '/instances'))) + self.assertTrue(MonitorJob(_REMOTE, lambda: DoPost + (_REMOTE, '/queries/%s/retrieve' % a, + '{"TargetAet":"ORTHANCTEST","Synchronous":false}'))) + self.assertEqual(2, len(DoGet(_LOCAL, '/instances'))) + + + # Same test, at the patient level => only 1 instance is transfered + a = DoPost(_REMOTE, '/modalities/self/query', { + 'Level' : 'Patient', + 'Query' : {"PatientID": "A" }})['ID'] + self.assertEqual(1, len(DoGet(_REMOTE, '/queries/%s/answers' % a))) + DropOrthanc(_LOCAL) + self.assertEqual(0, len(DoGet(_LOCAL, '/instances'))) + self.assertTrue(MonitorJob(_REMOTE, lambda: DoPost + (_REMOTE, '/queries/%s/retrieve' % a, + '{"TargetAet":"ORTHANCTEST","Synchronous":false}'))) + self.assertEqual(1, len(DoGet(_LOCAL, '/instances'))) + + + # Same test, at the series level => only 1 instance is transfered + a = DoPost(_REMOTE, '/modalities/self/query', { + 'Level' : 'Series', + 'Query' : {"PatientID": "A" }})['ID'] + self.assertEqual(1, len(DoGet(_REMOTE, '/queries/%s/answers' % a))) + DropOrthanc(_LOCAL) + self.assertEqual(0, len(DoGet(_LOCAL, '/instances'))) + self.assertTrue(MonitorJob(_REMOTE, lambda: DoPost + (_REMOTE, '/queries/%s/retrieve' % a, + '{"TargetAet":"ORTHANCTEST","Synchronous":false}'))) + self.assertEqual(1, len(DoGet(_LOCAL, '/instances'))) +