changeset 790:3da6edb11ee9

merge
author Alain Mazy <am@orthanc.team>
date Tue, 25 Feb 2025 19:27:02 +0100
parents 36486b8031bb (diff) d753dc94de2c (current diff)
children 5140a8917254 f930532604bb 8dfe8f2590b0
files Tests/Tests.py
diffstat 3 files changed, 191 insertions(+), 35 deletions(-) [+]
line wrap: on
line diff
--- a/NewTests/Authorization/test_authorization.py	Mon Feb 24 08:03:48 2025 +0100
+++ b/NewTests/Authorization/test_authorization.py	Tue Feb 25 19:27:02 2025 +0100
@@ -57,7 +57,8 @@
                 },
                 "DicomWeb": {
                     "Enable": True
-                }
+                },
+                "StableAge": 5000 # not to be disturbed by StableAge events while debugging
             }
 
         config_path = cls.generate_configuration(
@@ -121,6 +122,17 @@
         cls.no_label_series_dicom_id = o.series.get_tags(cls.no_label_series_id)["SeriesInstanceUID"]
         cls.no_label_instance_dicom_id = o.instances.get_tags(cls.no_label_instance_id)["SOPInstanceUID"]
 
+        cls.both_labels_instance_id = o.upload_file(here / "../../Database/Phenix/IM-0001-0001.dcm")[0]
+        cls.both_labels_study_id = o.instances.get_parent_study_id(cls.both_labels_instance_id)
+        cls.both_labels_series_id = o.instances.get_parent_series_id(cls.both_labels_instance_id)
+        cls.both_labels_study_dicom_id = o.studies.get_tags(cls.both_labels_study_id)["StudyInstanceUID"]
+        cls.both_labels_series_dicom_id = o.series.get_tags(cls.both_labels_series_id)["SeriesInstanceUID"]
+        cls.both_labels_instance_dicom_id = o.instances.get_tags(cls.both_labels_instance_id)["SOPInstanceUID"]
+        o.studies.add_label(cls.both_labels_study_id, "label_a")
+        o.studies.add_label(cls.both_labels_study_id, "label_b")
+        o.series.add_label(cls.both_labels_series_id, "label_a")
+        o.series.add_label(cls.both_labels_series_id, "label_b")
+
 
     def assert_is_forbidden(self, api_call):
         with self.assertRaises(orthanc_exceptions.HttpError) as ctx:
@@ -145,14 +157,15 @@
         instances_ids = o.series.get_instances_ids(series_ids[0])
         o.instances.get_tags(instances_ids[0])
 
-        # make sure labels filtering still works
-        self.assertEqual(3, len(o.studies.find(query={},
-                                               labels=[],
-                                               labels_constraint='Any')))
+        if o.is_plugin_version_at_least("authorization", 0, 9, 0):
+            # make sure labels filtering still works
+            self.assertEqual(4, len(o.studies.find(query={},
+                                                labels=[],
+                                                labels_constraint='Any')))
 
-        self.assertEqual(2, len(o.studies.find(query={},
-                                               labels=['label_a', 'label_b'],
-                                               labels_constraint='Any')))
+            self.assertEqual(3, len(o.studies.find(query={},
+                                                labels=['label_a', 'label_b'],
+                                                labels_constraint='Any')))
 
         self.assertEqual(2, len(o.studies.find(query={},
                                                labels=['label_a'],
@@ -192,19 +205,24 @@
         # make sure we can not access series and instances of the label_b studies
         self.assert_is_forbidden(lambda: o.studies.get_series_ids(self.label_b_study_id))
 
-        # make sure tools/find only returns the label_a studies
-        studies = o.studies.find(query={},
-                                 labels=[],
-                                 labels_constraint='Any')
-        self.assertEqual(1, len(studies))
-        self.assertEqual(self.label_a_study_id, studies[0].orthanc_id)
+        if o_admin.is_plugin_version_at_least("authorization", 0, 9, 0):
+            # make sure tools/find only returns the label_a studies
+            studies = o.studies.find(query={},
+                                    labels=[],
+                                    labels_constraint='Any')
+            studies_orthanc_ids = [x.orthanc_id for x in studies]
+            self.assertEqual(2, len(studies_orthanc_ids))
+            self.assertIn(self.label_a_study_id, studies_orthanc_ids)
+            self.assertIn(self.both_labels_study_id, studies_orthanc_ids)
 
-        # if searching Any of label_a & label_b, return only label_a
-        studies = o.studies.find(query={},
-                                 labels=['label_a', 'label_b'],
-                                 labels_constraint='Any')
-        self.assertEqual(1, len(studies))
-        self.assertEqual(self.label_a_study_id, studies[0].orthanc_id)
+            # if searching Any of label_a & label_b, return only label_a
+            studies = o.studies.find(query={},
+                                    labels=['label_a', 'label_b'],
+                                    labels_constraint='Any')
+            studies_orthanc_ids = [x.orthanc_id for x in studies]
+            self.assertEqual(2, len(studies_orthanc_ids))
+            self.assertIn(self.label_a_study_id, studies_orthanc_ids)
+            self.assertIn(self.both_labels_study_id, studies_orthanc_ids)
 
         # if searching Any of label_b, expect a Forbidden access
         self.assert_is_forbidden(lambda: o.studies.find(query={},
@@ -272,6 +290,31 @@
             i = o_admin.get_binary(f"dicom-web/studies/{self.label_a_study_dicom_id}/series/{self.label_a_series_dicom_id}/instances/{self.label_a_instance_dicom_id}")
             i = o_admin.get_json(f"dicom-web/studies/{self.label_a_study_dicom_id}/series?includefield=00080021%2C00080031%2C0008103E%2C00200011")
 
+        if o_admin.is_plugin_version_at_least("authorization", 0, 9, 0):
+            # the user_a shall only see the label_a in the returned labels
+            studies = o.post(endpoint="/tools/find", json={"Level": "Study", "Query": {}, "Labels": [], "LabelsConstraint": "Any", "Expand": True}).json()
+            self.assertEqual(2, len(studies))
+            self.assertEqual(1, len(studies[0]["Labels"]))
+            self.assertEqual("label_a", studies[0]["Labels"][0])
+            self.assertEqual(1, len(studies[1]["Labels"]))
+            self.assertEqual("label_a", studies[1]["Labels"][0])
+
+            r = o.get(endpoint=f"/studies/{self.both_labels_study_id}").json()
+            self.assertEqual(1, len(r["Labels"]))
+            self.assertEqual("label_a", r["Labels"][0])
+
+            r = o.get(endpoint=f"/studies/{self.both_labels_study_id}/series?expand").json()
+            self.assertEqual(1, len(r[0]["Labels"]))
+            self.assertEqual("label_a", r[0]["Labels"][0])
+
+            r = o.get(endpoint=f"/studies/{self.both_labels_study_id}/labels").json()
+            self.assertEqual(1, len(r))
+            self.assertEqual("label_a", r[0])
+
+            r = o.get(endpoint=f"/series/{self.both_labels_series_id}/study").json()
+            self.assertEqual(1, len(r["Labels"]))
+            self.assertEqual("label_a", r["Labels"][0])
+
 
     def test_uploader_a(self):
         o_admin = OrthancApiClient(self.o._root_url, headers={"user-token-key": "token-admin"})
--- a/NewTests/requirements.txt	Mon Feb 24 08:03:48 2025 +0100
+++ b/NewTests/requirements.txt	Tue Feb 25 19:27:02 2025 +0100
@@ -1,3 +1,3 @@
-orthanc-api-client>=0.18.0
+orthanc-api-client>=0.18.4
 orthanc-tools>=0.13.0
 uvicorn
\ No newline at end of file
--- a/Tests/Tests.py	Mon Feb 24 08:03:48 2025 +0100
+++ b/Tests/Tests.py	Tue Feb 25 19:27:02 2025 +0100
@@ -6738,6 +6738,21 @@
             else:
                 self.assertEqual(a, b)
 
+        if IsOrthancVersionAbove(_REMOTE, 1, 12, 7) and HasExtendedFind(_REMOTE):
+            transcoded = DoPost(_REMOTE, '/instances/%s/modify' % i, {
+                'Transcode' : '1.2.840.10008.1.2.4.50',
+                'LossyQuality': 40
+                })
+            ratio40 = ExtractDicomTags(transcoded, [ 'LossyImageCompressionRatio' ]) [0]
+
+            transcoded = DoPost(_REMOTE, '/instances/%s/modify' % i, {
+                'Transcode' : '1.2.840.10008.1.2.4.50',
+                'LossyQuality': 80
+                })
+            ratio80 = ExtractDicomTags(transcoded, [ 'LossyImageCompressionRatio' ]) [0]
+            self.assertGreater(ratio40, ratio80)
+
+
     def test_archive_transcode(self):
         info = UploadInstance(_REMOTE, 'KarstenHilbertRF.dcm')
 
@@ -6757,6 +6772,14 @@
         z, resp = GetArchive(_REMOTE, '/series/%s/media?transcode=1.2.840.10008.1.2.4.57' % info['ParentSeries'])
         self.assertEqual('1.2.840.10008.1.2.4.57', GetTransferSyntax(z.read('IMAGES/IM0')))
 
+        if IsOrthancVersionAbove(_REMOTE, 1, 12, 7) and HasExtendedFind(_REMOTE):
+            z40, resp40 = GetArchive(_REMOTE, '/patients/%s/media?transcode=1.2.840.10008.1.2.4.50&lossy-quality=40' % info['ParentPatient'])
+            z80, resp80 = GetArchive(_REMOTE, '/patients/%s/media?transcode=1.2.840.10008.1.2.4.50&lossy-quality=80' % info['ParentPatient'])
+
+            size40 = sum([zinfo.file_size for zinfo in z40.filelist])
+            size80 = sum([zinfo.file_size for zinfo in z80.filelist])
+            self.assertLess(size40, size80)
+
 
         # POST on "/media"
         self.assertRaises(Exception, lambda: PostArchive(
@@ -6777,6 +6800,20 @@
             })
         self.assertEqual('1.2.840.10008.1.2.4.57', GetTransferSyntax(z.read('IMAGES/IM0')))
 
+        if IsOrthancVersionAbove(_REMOTE, 1, 12, 7) and HasExtendedFind(_REMOTE):
+            z40 = PostArchive(_REMOTE, '/series/%s/media' % info['ParentSeries'], {
+                'Transcode' : '1.2.840.10008.1.2.4.50',
+                'LossyQuality': 40
+                })
+            z80 = PostArchive(_REMOTE, '/series/%s/media' % info['ParentSeries'], {
+                'Transcode' : '1.2.840.10008.1.2.4.50',
+                'LossyQuality': 80
+                })
+
+            size40 = sum([zinfo.file_size for zinfo in z40.filelist])
+            size80 = sum([zinfo.file_size for zinfo in z80.filelist])
+            self.assertLess(size40, size80)
+
         
         # GET on "/archive"
         z, resp = GetArchive(_REMOTE, '/patients/%s/archive' % info['ParentPatient'])
@@ -6794,6 +6831,14 @@
         z, resp = GetArchive(_REMOTE, '/series/%s/archive?transcode=1.2.840.10008.1.2.4.70' % info['ParentSeries'])
         self.assertEqual('1.2.840.10008.1.2.4.70', GetTransferSyntax(z.read(z.namelist()[0])))
 
+        if IsOrthancVersionAbove(_REMOTE, 1, 12, 7) and HasExtendedFind(_REMOTE):
+            z40, resp40 = GetArchive(_REMOTE, '/patients/%s/archive?transcode=1.2.840.10008.1.2.4.50&lossy-quality=40' % info['ParentPatient'])
+            z80, resp80 = GetArchive(_REMOTE, '/patients/%s/archive?transcode=1.2.840.10008.1.2.4.50&lossy-quality=80' % info['ParentPatient'])
+
+            size40 = sum([zinfo.file_size for zinfo in z40.filelist])
+            size80 = sum([zinfo.file_size for zinfo in z80.filelist])
+            self.assertLess(size40, size80)
+
 
         # POST on "/archive"
         self.assertRaises(Exception, lambda: PostArchive(
@@ -6814,6 +6859,20 @@
             })
         self.assertEqual('1.2.840.10008.1.2.4.57', GetTransferSyntax(z.read(z.namelist()[0])))
         
+        if IsOrthancVersionAbove(_REMOTE, 1, 12, 7) and HasExtendedFind(_REMOTE):
+            z40 = PostArchive(_REMOTE, '/series/%s/archive' % info['ParentSeries'], {
+                'Transcode' : '1.2.840.10008.1.2.4.50',
+                'LossyQuality': 40
+                })
+            z80 = PostArchive(_REMOTE, '/series/%s/archive' % info['ParentSeries'], {
+                'Transcode' : '1.2.840.10008.1.2.4.50',
+                'LossyQuality': 80
+                })
+
+            size40 = sum([zinfo.file_size for zinfo in z40.filelist])
+            size80 = sum([zinfo.file_size for zinfo in z80.filelist])
+            self.assertLess(size40, size80)
+
 
         # "/tools/create-*"
         z = PostArchive(_REMOTE, '/tools/create-archive', {
@@ -6852,28 +6911,82 @@
             if IsOrthancVersionAbove(_REMOTE, 1, 12, 7):
                 self.assertEqual('filename="toto.zip"', resp['content-disposition'])
 
-
+        if IsOrthancVersionAbove(_REMOTE, 1, 12, 7) and HasExtendedFind(_REMOTE):
+            z40 = PostArchive(_REMOTE, '/tools/create-archive', {
+                'Resources' : [ info['ParentStudy'] ],
+                'Transcode' : '1.2.840.10008.1.2.4.50',
+                'LossyQuality': 40
+                })
+            z80 = PostArchive(_REMOTE, '/tools/create-archive', {
+                'Resources' : [ info['ParentStudy'] ],
+                'Transcode' : '1.2.840.10008.1.2.4.50',
+                'LossyQuality': 80
+                })
+                
+            size40 = sum([zinfo.file_size for zinfo in z40.filelist])
+            size80 = sum([zinfo.file_size for zinfo in z80.filelist])
+            self.assertLess(size40, size80)
+
+            z40 = PostArchive(_REMOTE, '/tools/create-media', {
+                'Resources' : [ info['ParentStudy'] ],
+                'Transcode' : '1.2.840.10008.1.2.4.50',
+                'LossyQuality': 40
+                })
+            z80 = PostArchive(_REMOTE, '/tools/create-media', {
+                'Resources' : [ info['ParentStudy'] ],
+                'Transcode' : '1.2.840.10008.1.2.4.50',
+                'LossyQuality': 80
+                })
+                
+            size40 = sum([zinfo.file_size for zinfo in z40.filelist])
+            size80 = sum([zinfo.file_size for zinfo in z80.filelist])
+            self.assertLess(size40, size80)
+
+            z40 = PostArchive(_REMOTE, '/tools/create-media-extended', {
+                'Resources' : [ info['ParentStudy'] ],
+                'Transcode' : '1.2.840.10008.1.2.4.50',
+                'LossyQuality': 40
+                })
+            z80 = PostArchive(_REMOTE, '/tools/create-media-extended', {
+                'Resources' : [ info['ParentStudy'] ],
+                'Transcode' : '1.2.840.10008.1.2.4.50',
+                'LossyQuality': 80
+                })
+                
+            size40 = sum([zinfo.file_size for zinfo in z40.filelist])
+            size80 = sum([zinfo.file_size for zinfo in z80.filelist])
+            self.assertLess(size40, size80)
+
+            z40, resp = GetArchive(_REMOTE, '/tools/create-archive?resources=%s&transcode=1.2.840.10008.1.2.4.50&lossy-quality=40' % info['ParentStudy'])
+            z80, resp = GetArchive(_REMOTE, '/tools/create-archive?resources=%s&transcode=1.2.840.10008.1.2.4.50&lossy-quality=80' % info['ParentStudy'])
+            size40 = sum([zinfo.file_size for zinfo in z40.filelist])
+            size80 = sum([zinfo.file_size for zinfo in z80.filelist])
+            self.assertLess(size40, size80)
 
 
     def test_download_file_transcode(self):
         if IsOrthancVersionAbove(_REMOTE, 1, 12, 2):
 
             info = UploadInstance(_REMOTE, 'TransferSyntaxes/1.2.840.10008.1.2.1.dcm')
-            self.assertEqual('1.2.840.10008.1.2.1', GetTransferSyntax(
-                DoGet(_REMOTE, '/instances/%s/file' % info['ID'])))
-
-            self.assertEqual('1.2.840.10008.1.2.4.50', GetTransferSyntax(
-                DoGet(_REMOTE, '/instances/%s/file?transcode=1.2.840.10008.1.2.4.50' % info['ID'])))
+            # self.assertEqual('1.2.840.10008.1.2.1', GetTransferSyntax(
+            #     DoGet(_REMOTE, '/instances/%s/file' % info['ID'])))
+
+            # self.assertEqual('1.2.840.10008.1.2.4.50', GetTransferSyntax(
+            #     DoGet(_REMOTE, '/instances/%s/file?transcode=1.2.840.10008.1.2.4.50' % info['ID'])))
 
             if IsOrthancVersionAbove(_REMOTE, 1, 12, 7):
-                resp, content = DoGetRaw(_REMOTE, '/instances/%s/file?filename=toto.dcm' % info['ID'])
-                self.assertEqual('filename="toto.dcm"', resp['content-disposition'])
-
-                resp, content = DoGetRaw(_REMOTE, '/instances/%s/file?transcode=1.2.840.10008.1.2.4.50&filename=toto.dcm' % info['ID'])
-                self.assertEqual('filename="toto.dcm"', resp['content-disposition'])
-
-                resp, content = DoGetRaw(_REMOTE, '/instances/%s/file?filename="toto".dcm' % info['ID'])
-                self.assertEqual('filename="\"toto\".dcm"', resp['content-disposition'])
+                # resp, content = DoGetRaw(_REMOTE, '/instances/%s/file?filename=toto.dcm' % info['ID'])
+                # self.assertEqual('filename="toto.dcm"', resp['content-disposition'])
+
+                # resp, content = DoGetRaw(_REMOTE, '/instances/%s/file?transcode=1.2.840.10008.1.2.4.50&filename=toto.dcm' % info['ID'])
+                # self.assertEqual('filename="toto.dcm"', resp['content-disposition'])
+
+                # resp, content = DoGetRaw(_REMOTE, '/instances/%s/file?filename="toto".dcm' % info['ID'])
+                # self.assertEqual('filename="\"toto\".dcm"', resp['content-disposition'])
+
+                resp, content40 = DoGetRaw(_REMOTE, '/instances/%s/file?transcode=1.2.840.10008.1.2.4.50&lossy-quality=40' % info['ID'])
+                resp, content80 = DoGetRaw(_REMOTE, '/instances/%s/file?transcode=1.2.840.10008.1.2.4.50&lossy-quality=80' % info['ID'])
+                self.assertLess(len(content40), len(content80))
 
 
     def test_modify_keep_source(self):