changeset 624:543e372d2265

added a PG max storage test
author Alain Mazy <am@osimis.io>
date Wed, 14 Feb 2024 11:25:40 +0100
parents 3bb4b2589030
children 78314ab6fc67
files NewTests/Concurrency/test_concurrency.py NewTests/MaxStorage/__init__.py NewTests/MaxStorage/test_max_storage_pg.py NewTests/MaxStorage/test_max_storage_reject.py NewTests/MaxStorageReject/__init__.py NewTests/MaxStorageReject/test_max_storage_reject.py NewTests/README
diffstat 5 files changed, 273 insertions(+), 133 deletions(-) [+]
line wrap: on
line diff
--- a/NewTests/Concurrency/test_concurrency.py	Wed Feb 07 11:43:32 2024 +0100
+++ b/NewTests/Concurrency/test_concurrency.py	Wed Feb 14 11:25:40 2024 +0100
@@ -7,8 +7,6 @@
 from orthanc_api_client import OrthancApiClient, ChangeType
 from orthanc_api_client import helpers as OrthancHelpers
 
-from orthanc_tools import OrthancTestDbPopulator
-
 import pathlib
 import subprocess
 import glob
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/NewTests/MaxStorage/test_max_storage_pg.py	Wed Feb 14 11:25:40 2024 +0100
@@ -0,0 +1,134 @@
+import unittest
+import time
+import os
+import threading
+from helpers import OrthancTestCase, Helpers
+
+from orthanc_api_client import OrthancApiClient, ChangeType
+from orthanc_api_client.exceptions import HttpError
+from orthanc_api_client import helpers as OrthancHelpers
+
+from orthanc_tools import OrthancTestDbPopulator
+
+import pathlib
+import subprocess
+import glob
+here = pathlib.Path(__file__).parent.resolve()
+
+
+class TestMaxStoragePG(OrthancTestCase):
+
+    @classmethod
+    def terminate(cls):
+
+        if Helpers.is_docker():
+            subprocess.run(["docker", "rm", "-f", "pg-server"])
+        else:
+            cls.pg_service_process.terminate()
+
+
+    @classmethod
+    def prepare(cls):
+        test_name = "MaxStoragePG"
+        cls._storage_name = "max-storage-pg"
+        network_name = "max-storage-pg"
+
+        print(f'-------------- preparing {test_name} tests')
+
+        cls.clear_storage(storage_name=cls._storage_name)
+
+        pg_hostname = "localhost"
+        if Helpers.is_docker():
+            pg_hostname = "pg-server"
+            cls.create_docker_network(network_name)
+
+        config = { 
+            "PostgreSQL" : {
+                "EnableStorage": False,
+                "EnableIndex": True,
+                "Host": pg_hostname,
+                "Port": 5432,
+                "Database": "postgres",
+                "Username": "postgres",
+                "Password": "postgres",
+                "IndexConnectionsCount": 10,
+                "MaximumConnectionRetries" : 2000,
+                "ConnectionRetryInterval" : 5,
+                "TransactionMode": "ReadCommitted",
+                #"TransactionMode": "Serializable",
+                "EnableVerboseLogs": True
+            },
+            "AuthenticationEnabled": False,
+            "OverwriteInstances": True,
+            "MaximumStorageSize": 1,
+            "MaximumStorageMode": "Recycle"
+            # "MaximumPatientCount": 1,
+            # "MaximumStorageMode": "Reject"
+        }
+
+        config_path = cls.generate_configuration(
+            config_name=f"{test_name}",
+            storage_name=cls._storage_name,
+            config=config,
+            plugins=Helpers.plugins
+        )
+
+        # launch the docker PG server
+        print('--------------- launching PostgreSQL server ------------------')
+
+        pg_cmd = [            
+            "docker", "run", "--rm", 
+            "-p", "5432:5432", 
+            "--name", "pg-server",
+            "--env", "POSTGRES_HOST_AUTH_METHOD=trust"
+            ]
+        
+        if Helpers.is_docker():
+            pg_cmd.extend(["--network", network_name])
+        pg_cmd.append("postgres:15")
+
+        cls.pg_service_process = subprocess.Popen(pg_cmd)
+        time.sleep(5)
+
+        if Helpers.break_after_preparation:
+            print(f"++++ It is now time to start your Orthanc under tests with configuration file '{config_path}' +++++")
+            input("Press Enter to continue")
+        else:
+            cls.launch_orthanc_under_tests(
+                config_name=f"{test_name}",
+                storage_name=cls._storage_name,
+                config=config,
+                plugins=Helpers.plugins,
+                docker_network=network_name
+            )
+
+        cls.o = OrthancApiClient(cls.o._root_url)
+        cls.o.wait_started()
+        cls.o.delete_all_content()
+
+
+    def test_upload(self):
+        self.o.delete_all_content()
+        self.clear_storage(storage_name=self._storage_name)
+
+        uploaded_instances_ids = []
+        counter = 0
+        # upload 10 images of 500x500, since the MaximumStorageSize is 1MB, only 2 of them should remain in the storage
+        for i in range(0, 10):
+            counter += 1
+            dicom_file = OrthancHelpers.generate_test_dicom_file(width=500, height=500,
+                                                                tags = {
+                                                                    "PatientID" : f"{i}",
+                                                                    "StudyInstanceUID" : f"{i}",
+                                                                    "SeriesInstanceUID" : f"{i}.{counter%10}"
+                                                                })
+            try:
+                uploaded_instances_ids.extend(self.o.upload(dicom_file))
+            except HttpError as er:
+                if er.http_status_code == 507:
+                    pass  # ignore
+
+        # some instances have been discarded
+        self.assertLess(len(self.o.instances.get_all_ids()), 10)
+        self.assertLess(len(self.o.patients.get_all_ids()), 10)
+        self.assertLess(self.o.get_statistics().total_disk_size, 1*1024*1024)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/NewTests/MaxStorage/test_max_storage_reject.py	Wed Feb 14 11:25:40 2024 +0100
@@ -0,0 +1,127 @@
+import unittest
+import time
+import subprocess
+import pprint
+import os
+from helpers import OrthancTestCase, Helpers
+
+from orthanc_api_client import OrthancApiClient, generate_test_dicom_file
+from orthanc_api_client import exceptions as orthanc_exceptions
+
+import pathlib
+here = pathlib.Path(__file__).parent.resolve()
+
+
+def count_files_in_storage(path):
+    all_files = []
+    for root, dirs, files in os.walk(path):
+        for file in files:
+            if len(file) == 36:
+                all_files.append(file)
+    
+    return len(all_files)
+
+
+class TestMaxStorageReject(OrthancTestCase):
+
+    @classmethod
+    def prepare(cls):
+        test_name = "MaxStorageReject"
+        storage_name = "max_storage_reject"
+
+        cls.clear_storage(storage_name=storage_name)
+
+        config_path = cls.generate_configuration(
+            config_name=f"{test_name}_under_test",
+            storage_name=storage_name,
+            config={
+                "MaximumPatientCount": 2,
+                "MaximumStorageMode": "Reject"
+            },
+            plugins=Helpers.plugins
+        )
+
+        print(f'-------------- prepared {test_name} tests')
+        if Helpers.break_after_preparation:
+            print(f"++++ It is now time to start your Orthanc under tests with configuration file '{config_path}' +++++")
+            input("Press Enter to continue")
+        else:
+            print(f'-------------- launching {test_name} tests')
+            cls.launch_orthanc_under_tests(
+                config_path=config_path,
+                config_name=f"{test_name}_under_test",
+                storage_name=storage_name,
+                plugins=Helpers.plugins
+            )
+
+        print('-------------- waiting for orthanc-under-tests to be available')
+        cls.o.wait_started()
+
+
+    def test_upload_3_patients_rest_api(self):
+        
+        if self.o.get_system()["ApiVersion"] > 20:  # from Orthanc 1.12.1
+            self.o.delete_all_content()
+
+            # make sure the 3rd patient does not make it into the storage (through the Rest API)
+            self.o.upload_file(here / "../../Database/Brainix/Flair/IM-0001-0001.dcm")
+            self.o.upload_file(here / "../../Database/Knix/Loc/IM-0001-0001.dcm")
+            with self.assertRaises(orthanc_exceptions.HttpError) as ctx:
+                self.o.upload_file(here / "../../Database/Phenix/IM-0001-0001.dcm")
+            self.assertEqual(507, ctx.exception.http_status_code)
+            self.assertEqual(2, len(self.o.studies.get_all_ids()))
+            self.assertEqual(2, count_files_in_storage(self.get_storage_path("max_storage_reject")))
+
+    def upload_with_store_scu(self, path):
+        subprocess.check_call([Helpers.find_executable('storescu'),
+                               "-xs",
+                               Helpers.get_orthanc_ip(),
+                               str(Helpers.get_orthanc_dicom_port()),
+                               path])
+
+    def test_upload_3_patients_c_store(self):
+
+        if self.o.get_system()["ApiVersion"] > 20:  # from Orthanc 1.12.1
+            self.o.delete_all_content()
+            
+            # make sure the 3rd patient does not make it into the storage (through StoreSCU)
+            self.upload_with_store_scu(here / "../../Database/Brainix/Flair/IM-0001-0001.dcm")
+            self.upload_with_store_scu(here / "../../Database/Knix/Loc/IM-0001-0001.dcm")
+            with self.assertRaises(subprocess.CalledProcessError) as ctx:
+                self.upload_with_store_scu(here / "../../Database/Phenix/IM-0001-0001.dcm")
+            self.assertEqual(2, len(self.o.studies.get_all_ids()))
+            self.assertEqual(2, count_files_in_storage(self.get_storage_path("max_storage_reject")))
+
+    def test_upload_3_patients_dicomweb(self):
+
+        if self.o.get_system()["ApiVersion"] > 20:  # from Orthanc 1.12.1
+            self.o.delete_all_content()
+            
+            # make sure the 3rd patient does not make it into the storage (through DicomWeb)
+            self.o.upload_files_dicom_web([here / "../../Database/Brainix/Flair/IM-0001-0001.dcm"])
+            self.o.upload_files_dicom_web([here / "../../Database/Knix/Loc/IM-0001-0001.dcm"])
+
+            with self.assertRaises(orthanc_exceptions.HttpError) as ctx:
+                self.o.upload_files_dicom_web([here / "../../Database/Phenix/IM-0001-0001.dcm"])
+            self.assertEqual(400, ctx.exception.http_status_code)
+
+            self.assertEqual(2, len(self.o.studies.get_all_ids()))
+            self.assertEqual(2, count_files_in_storage(self.get_storage_path("max_storage_reject")))
+
+    def test_upload_3_patients_dicomweb_in_one_query(self):
+
+        if self.o.get_system()["ApiVersion"] > 20:  # from Orthanc 1.12.1
+            self.o.delete_all_content()
+            
+            # make sure the 3rd patient does not make it into the storage (through DicomWeb)
+            r = self.o.upload_files_dicom_web([
+                here / "../../Database/Brainix/Flair/IM-0001-0001.dcm",
+                here / "../../Database/Knix/Loc/IM-0001-0001.dcm",
+                here / "../../Database/Phenix/IM-0001-0001.dcm"
+                ])
+
+            # pprint.pprint(r)
+            self.assertEqual(2, len(self.o.studies.get_all_ids()))
+            self.assertIn('00081198', r)
+            self.assertEqual(0xA700, r['00081198']['Value'][0]['00081197']['Value'][0])  # one failed instance with out-of-resource status
+            self.assertEqual(2, count_files_in_storage(self.get_storage_path("max_storage_reject")))
--- a/NewTests/MaxStorageReject/test_max_storage_reject.py	Wed Feb 07 11:43:32 2024 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,127 +0,0 @@
-import unittest
-import time
-import subprocess
-import pprint
-import os
-from helpers import OrthancTestCase, Helpers
-
-from orthanc_api_client import OrthancApiClient, generate_test_dicom_file
-from orthanc_api_client import exceptions as orthanc_exceptions
-
-import pathlib
-here = pathlib.Path(__file__).parent.resolve()
-
-
-def count_files_in_storage(path):
-    all_files = []
-    for root, dirs, files in os.walk(path):
-        for file in files:
-            if len(file) == 36:
-                all_files.append(file)
-    
-    return len(all_files)
-
-
-class TestMaxStorageReject(OrthancTestCase):
-
-    @classmethod
-    def prepare(cls):
-        test_name = "MaxStorageReject"
-        storage_name = "max_storage_reject"
-
-        cls.clear_storage(storage_name=storage_name)
-
-        config_path = cls.generate_configuration(
-            config_name=f"{test_name}_under_test",
-            storage_name=storage_name,
-            config={
-                "MaximumPatientCount": 2,
-                "MaximumStorageMode": "Reject"
-            },
-            plugins=Helpers.plugins
-        )
-
-        print(f'-------------- prepared {test_name} tests')
-        if Helpers.break_after_preparation:
-            print(f"++++ It is now time to start your Orthanc under tests with configuration file '{config_path}' +++++")
-            input("Press Enter to continue")
-        else:
-            print(f'-------------- launching {test_name} tests')
-            cls.launch_orthanc_under_tests(
-                config_path=config_path,
-                config_name=f"{test_name}_under_test",
-                storage_name=storage_name,
-                plugins=Helpers.plugins
-            )
-
-        print('-------------- waiting for orthanc-under-tests to be available')
-        cls.o.wait_started()
-
-
-    def test_upload_3_patients_rest_api(self):
-        
-        if self.o.get_system()["ApiVersion"] > 20:  # from Orthanc 1.12.1
-            self.o.delete_all_content()
-
-            # make sure the 3rd patient does not make it into the storage (through the Rest API)
-            self.o.upload_file(here / "../../Database/Brainix/Flair/IM-0001-0001.dcm")
-            self.o.upload_file(here / "../../Database/Knix/Loc/IM-0001-0001.dcm")
-            with self.assertRaises(orthanc_exceptions.HttpError) as ctx:
-                self.o.upload_file(here / "../../Database/Phenix/IM-0001-0001.dcm")
-            self.assertEqual(507, ctx.exception.http_status_code)
-            self.assertEqual(2, len(self.o.studies.get_all_ids()))
-            self.assertEqual(2, count_files_in_storage(self.get_storage_path("max_storage_reject")))
-
-    def upload_with_store_scu(self, path):
-        subprocess.check_call([Helpers.find_executable('storescu'),
-                               "-xs",
-                               Helpers.get_orthanc_ip(),
-                               str(Helpers.get_orthanc_dicom_port()),
-                               path])
-
-    def test_upload_3_patients_c_store(self):
-
-        if self.o.get_system()["ApiVersion"] > 20:  # from Orthanc 1.12.1
-            self.o.delete_all_content()
-            
-            # make sure the 3rd patient does not make it into the storage (through StoreSCU)
-            self.upload_with_store_scu(here / "../../Database/Brainix/Flair/IM-0001-0001.dcm")
-            self.upload_with_store_scu(here / "../../Database/Knix/Loc/IM-0001-0001.dcm")
-            with self.assertRaises(subprocess.CalledProcessError) as ctx:
-                self.upload_with_store_scu(here / "../../Database/Phenix/IM-0001-0001.dcm")
-            self.assertEqual(2, len(self.o.studies.get_all_ids()))
-            self.assertEqual(2, count_files_in_storage(self.get_storage_path("max_storage_reject")))
-
-    def test_upload_3_patients_dicomweb(self):
-
-        if self.o.get_system()["ApiVersion"] > 20:  # from Orthanc 1.12.1
-            self.o.delete_all_content()
-            
-            # make sure the 3rd patient does not make it into the storage (through DicomWeb)
-            self.o.upload_files_dicom_web([here / "../../Database/Brainix/Flair/IM-0001-0001.dcm"])
-            self.o.upload_files_dicom_web([here / "../../Database/Knix/Loc/IM-0001-0001.dcm"])
-
-            with self.assertRaises(orthanc_exceptions.HttpError) as ctx:
-                self.o.upload_files_dicom_web([here / "../../Database/Phenix/IM-0001-0001.dcm"])
-            self.assertEqual(400, ctx.exception.http_status_code)
-
-            self.assertEqual(2, len(self.o.studies.get_all_ids()))
-            self.assertEqual(2, count_files_in_storage(self.get_storage_path("max_storage_reject")))
-
-    def test_upload_3_patients_dicomweb_in_one_query(self):
-
-        if self.o.get_system()["ApiVersion"] > 20:  # from Orthanc 1.12.1
-            self.o.delete_all_content()
-            
-            # make sure the 3rd patient does not make it into the storage (through DicomWeb)
-            r = self.o.upload_files_dicom_web([
-                here / "../../Database/Brainix/Flair/IM-0001-0001.dcm",
-                here / "../../Database/Knix/Loc/IM-0001-0001.dcm",
-                here / "../../Database/Phenix/IM-0001-0001.dcm"
-                ])
-
-            # pprint.pprint(r)
-            self.assertEqual(2, len(self.o.studies.get_all_ids()))
-            self.assertIn('00081198', r)
-            self.assertEqual(0xA700, r['00081198']['Value'][0]['00081197']['Value'][0])  # one failed instance with out-of-resource status
-            self.assertEqual(2, count_files_in_storage(self.get_storage_path("max_storage_reject")))
--- a/NewTests/README	Wed Feb 07 11:43:32 2024 +0100
+++ b/NewTests/README	Wed Feb 14 11:25:40 2024 +0100
@@ -120,18 +120,26 @@
 - execute tests
 
 
-MaxStorageReject:
-------------------
+MaxStorage:
+----------
 
-Run the MaxStorageReject tests with your locally build version and break before and after preparation
+Run the MaxStorage tests with your locally build version and break before and after preparation
 and execution to allow you to start your debugger.
 
-python3 NewTests/main.py --pattern=MaxStorageReject.test_max_storage_reject.TestMaxStorageReject.* \
+python3 NewTests/main.py --pattern=MaxStorage.test_max_storage_reject.TestMaxStorageReject.* \
                          --orthanc_under_tests_exe=/home/alain/o/build/orthanc/Orthanc \
                          --orthanc_under_tests_http_port=8043 \
                          --plugin=/home/alain/o/build/orthanc-dicomweb/libOrthancDicomWeb.so \
                          --break_after_preparation
 
+python3 NewTests/main.py --pattern=MaxStorage.test_max_storage_pg.TestMaxStoragePG.* \
+                         --orthanc_under_tests_exe=/home/alain/o/build/orthanc/Orthanc \
+                         --orthanc_under_tests_http_port=8043 \
+                         --plugin=/home/alain/o/build/orthanc-dicomweb/libOrthancDicomWeb.so \
+                         --plugin=/home/alain/o/build/pg/libOrthancPostgreSQLIndex.so \
+                         --break_after_preparation
+
+
 
 Authorization:
 --------------