# HG changeset patch # User Alain Mazy # Date 1660060677 -7200 # Node ID 10a47656e34f11e3d07a23ea2a73c51bb36f7684 # Parent 2078cb20a560dbb077119a63558cf4ff2e3ee0c8 new tests for MaximumStorageMode diff -r 2078cb20a560 -r 10a47656e34f NewTests/MaxStorageReject/__init__.py diff -r 2078cb20a560 -r 10a47656e34f NewTests/MaxStorageReject/test_max_storage_reject.py --- /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 diff -r 2078cb20a560 -r 10a47656e34f NewTests/README --- 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 + diff -r 2078cb20a560 -r 10a47656e34f NewTests/helpers.py --- 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 diff -r 2078cb20a560 -r 10a47656e34f Tests/Tests.py --- 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')