changeset 219:00e5aeea33dd

test_bitbucket_issue_131
author Sebastien Jodogne <s.jodogne@gmail.com>
date Sun, 24 Feb 2019 08:50:02 +0100
parents 70fba41776be
children 7b1c976caa9b
files .hgignore Database/PatientIdsCollision/Generate.sh Database/PatientIdsCollision/Issue131-a.dcm Database/PatientIdsCollision/Issue131-a.dump Database/PatientIdsCollision/Issue131-b.dcm Database/PatientIdsCollision/Issue131-b.dump Tests/Tests.py
diffstat 7 files changed, 88 insertions(+), 1 deletions(-) [+]
line wrap: on
line diff
--- 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/
+*~
--- 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
Binary file Database/PatientIdsCollision/Issue131-a.dcm has changed
--- /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
Binary file Database/PatientIdsCollision/Issue131-b.dcm has changed
--- /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
--- 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')))
+