changeset 490:10a47656e34f

new tests for MaximumStorageMode
author Alain Mazy <am@osimis.io>
date Tue, 09 Aug 2022 17:57:57 +0200
parents 2078cb20a560
children b517391a035f
files NewTests/MaxStorageReject/__init__.py NewTests/MaxStorageReject/test_max_storage_reject.py NewTests/README NewTests/helpers.py Tests/Tests.py
diffstat 4 files changed, 152 insertions(+), 2 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/NewTests/MaxStorageReject/test_max_storage_reject.py	Tue Aug 09 17:57:57 2022 +0200
@@ -0,0 +1,108 @@
+import unittest
+import time
+import subprocess
+import pprint
+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()
+
+
+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):
+        
+        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()))
+
+    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):
+
+        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()))
+
+    def test_upload_3_patients_dicomweb(self):
+
+        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()))
+
+    def test_upload_3_patients_dicomweb_in_one_query(self):
+
+        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
\ No newline at end of file
--- a/NewTests/README	Mon Aug 08 10:55:47 2022 +0200
+++ b/NewTests/README	Tue Aug 09 17:57:57 2022 +0200
@@ -101,3 +101,17 @@
 - drive this Orthanc to prepare the DB
 - interrupt and instruct you how to start your own version, pointing to the configuration file to use
 - execute tests
+
+
+MaxStorageReject:
+------------------
+
+Run the MaxStorageReject 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.* \
+                         --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
+
--- a/NewTests/helpers.py	Mon Aug 08 10:55:47 2022 +0200
+++ b/NewTests/helpers.py	Tue Aug 09 17:57:57 2022 +0200
@@ -2,7 +2,7 @@
 from orthanc_api_client import OrthancApiClient
 import subprocess
 import json
-import time
+import os
 import typing
 import shutil
 from threading import Thread
@@ -17,6 +17,7 @@
     "RemoteAccessAllowed": True
 }
 
+
 class Helpers:
 
     orthanc_under_tests_hostname: str = 'localhost'
@@ -35,6 +36,14 @@
         return f"http://{cls.orthanc_under_tests_hostname}:{cls.orthanc_under_tests_http_port}"
 
     @classmethod
+    def get_orthanc_ip(cls):
+        return cls.orthanc_under_tests_hostname
+
+    @classmethod
+    def get_orthanc_dicom_port(cls):
+        return cls.orthanc_under_tests_dicom_port
+
+    @classmethod
     def is_docker(cls):
         return cls.orthanc_under_tests_exe is None and cls.orthanc_under_tests_docker_image is not None
 
@@ -42,6 +51,19 @@
     def is_exe(cls):
         return cls.orthanc_under_tests_exe is not None and cls.orthanc_under_tests_docker_image is None
 
+    @classmethod
+    def find_executable(cls, name):
+        p = os.path.join('/usr/local/bin', name)
+        if os.path.isfile(p):
+            return p
+
+        p = os.path.join('/usr/local/sbin', name)
+        if os.path.isfile(p):
+            return p
+
+        return name
+
+
 class OrthancTestCase(unittest.TestCase):
 
     o: OrthancApiClient = None  # the orthanc under tests api client
--- a/Tests/Tests.py	Mon Aug 08 10:55:47 2022 +0200
+++ b/Tests/Tests.py	Tue Aug 09 17:57:57 2022 +0200
@@ -2477,6 +2477,10 @@
                 retries -= 1
                 with open(os.devnull, 'w') as FNULL:
                     try:
+
+                        print([ FindExecutable('storescu') ] + tmp +
+                                            [ _REMOTE['Server'], str(_REMOTE['DicomPort']),
+                                                GetDatabasePath(image) ])
                         subprocess.check_call([ FindExecutable('storescu') ] + tmp +
                                             [ _REMOTE['Server'], str(_REMOTE['DicomPort']),
                                                 GetDatabasePath(image) ],
@@ -2505,7 +2509,7 @@
         else:
             InstallLuaScriptFromPath(_REMOTE, 'Lua/TransferSyntaxDisable.lua')
         
-        # the following line regularly fails on CI because storescu still returns 0 although the C-Store fails !!
+        # the following line regularly fails on CI because storescu still returns 0 although the C-Store fails -> that's why we have implemented retries
         self.assertRaises(Exception, lambda: storescu('Knix/Loc/IM-0001-0001.dcm', False, False, 3))
         self.assertRaises(Exception, lambda: storescu('UnknownSopClassUid.dcm', True, False, 3))
         self.assertEqual(0, len(DoGet(_REMOTE, '/patients')))
@@ -2523,6 +2527,8 @@
         storescu('UnknownSopClassUid.dcm', True)
         self.assertEqual(2, len(DoGet(_REMOTE, '/patients')))
 
+        time.sleep(200)
+
         # set back normal verbosity
         DoPut(_REMOTE, '/tools/log-level', 'default')