# HG changeset patch # User Alain Mazy # Date 1651503942 -7200 # Node ID 6917a26881ed7ff74d0c8445535a9d46274e72ad # Parent 4ee85b016a4049067b2fb093e440163eab747438 NewTests working with Docker diff -r 4ee85b016a40 -r 6917a26881ed NewTests/Housekeeper/test_housekeeper.py --- a/NewTests/Housekeeper/test_housekeeper.py Sat Apr 30 19:38:34 2022 +0200 +++ b/NewTests/Housekeeper/test_housekeeper.py Mon May 02 17:05:42 2022 +0200 @@ -60,9 +60,11 @@ input("Press Enter to continue") else: print('-------------- launching TestHousekeeper tests') - cls.launch_orthanc( - exe_path=Helpers.orthanc_under_tests_exe, - config_path=config_path + cls.launch_orthanc_under_tests( + config_path=config_path, + config_name="housekepper_under_tests", + storage_name="housekeeper", + plugins=Helpers.plugins ) print('-------------- waiting for orthanc-under-tests to be available') diff -r 4ee85b016a40 -r 6917a26881ed NewTests/README --- a/NewTests/README Sat Apr 30 19:38:34 2022 +0200 +++ b/NewTests/README Mon May 02 17:05:42 2022 +0200 @@ -26,6 +26,8 @@ All-tests: --------- +with a local executable: + python3 NewTests/main.py --pattern=* \ --orthanc_under_tests_exe=/home/alain/o/build/orthanc/Orthanc \ --orthanc_under_tests_http_port=8043 \ @@ -33,6 +35,13 @@ --plugin=/home/alain/o/build/orthanc-gdcm/libOrthancGdcm.so +with Docker: + +python3 NewTests/main.py --pattern=* \ + --orthanc_under_tests_docker_image=osimis/orthanc:current \ + --orthanc_previous_version_docker_image=osimis/orthanc:22.4.0 \ + --orthanc_under_tests_http_port=8043 + Housekeeper: ----------- diff -r 4ee85b016a40 -r 6917a26881ed NewTests/helpers.py --- a/NewTests/helpers.py Sat Apr 30 19:38:34 2022 +0200 +++ b/NewTests/helpers.py Mon May 02 17:05:42 2022 +0200 @@ -20,7 +20,8 @@ class Helpers: orthanc_under_tests_hostname: str = 'localhost' - orthanc_under_tests_http_port: int = 8042 + orthanc_under_tests_http_port: int = 8052 + orthanc_under_tests_dicom_port: int = 4252 orthanc_under_tests_exe: str = None orthanc_previous_version_exe: str = None orthanc_under_tests_docker_image: str = None @@ -32,10 +33,19 @@ def get_orthanc_url(cls): return f"http://{cls.orthanc_under_tests_hostname}:{cls.orthanc_under_tests_http_port}" + @classmethod + def is_docker(cls): + return cls.orthanc_under_tests_exe is None and cls.orthanc_under_tests_docker_image is not None + + @classmethod + def is_exe(cls): + return cls.orthanc_under_tests_exe is not None and cls.orthanc_under_tests_docker_image is None + class OrthancTestCase(unittest.TestCase): o: OrthancApiClient = None # the orthanc under tests api client _orthanc_process = None + _orthanc_container_name = None _orthanc_is_running = False _orthanc_logger_thread = None @@ -67,9 +77,10 @@ def generate_configuration(cls, config_name: str, config: object, storage_name: str, plugins = []): # add plugins and default storge directory - config["Plugins"] = plugins + if plugins and len(plugins) > 0: + config["Plugins"] = plugins - if not "StorageDirectory" in config: + if Helpers.is_exe() and not "StorageDirectory" in config: config["StorageDirectory"] = cls.get_storage_path(storage_name=storage_name) if not "Name" in config: @@ -78,6 +89,9 @@ if not "HttpPort" in config: config["HttpPort"] = Helpers.orthanc_under_tests_http_port + if not "DicomPort" in config: + config["DicomPort"] = Helpers.orthanc_under_tests_dicom_port + # copy the values from the base config for k, v in default_base_config.items(): if not k in config: @@ -92,31 +106,72 @@ @classmethod def clear_storage(cls, storage_name: str): - storage_path = cls.get_storage_path(storage_name=storage_name) - shutil.rmtree(storage_path) - + if Helpers.is_exe(): + storage_path = cls.get_storage_path(storage_name=storage_name) + shutil.rmtree(storage_path, ignore_errors=True) + elif Helpers.is_docker(): + subprocess.run(["docker", "volume", "rm", storage_name]) @classmethod - def launch_orthanc_to_prepare_db(cls, config_name: str, config: object, storage_name: str, plugins = []): - # generate the configuration file - config_path = cls.generate_configuration( - config_name=config_name, - storage_name=storage_name, - config=config, - plugins=plugins - ) + def launch_orthanc_to_prepare_db(cls, config_name: str = None, config: object = None, config_path: str = None, storage_name: str = None, plugins = []): + if config_name and storage_name and config: + # generate the configuration file + config_path = cls.generate_configuration( + config_name=config_name, + storage_name=storage_name, + config=config, + plugins=plugins + ) + elif not config_path or not storage_name or not config_name: + raise RuntimeError("Invalid configuration") # run orthanc if Helpers.orthanc_previous_version_exe: - cls.launch_orthanc( + cls.launch_orthanc_exe( exe_path=Helpers.orthanc_previous_version_exe, config_path=config_path ) + elif Helpers.orthanc_previous_version_docker_image: + cls.launch_orthanc_docker( + docker_image=Helpers.orthanc_previous_version_docker_image, + storage_name=storage_name, + config_name=config_name, + config_path=config_path + ) else: - raise RuntimeError("No orthanc_previous_version_exe defined, can not launch Orthanc") + raise RuntimeError("Invalid configuration, can not launch Orthanc") @classmethod - def launch_orthanc(cls, exe_path: str, config_path: str): + def launch_orthanc_under_tests(cls, config_name: str = None, config: object = None, config_path: str = None, storage_name: str = None, plugins = []): + if config_name and storage_name and config: + # generate the configuration file + config_path = cls.generate_configuration( + config_name=config_name, + storage_name=storage_name, + config=config, + plugins=plugins + ) + elif not config_path or not storage_name or not config_name: + raise RuntimeError("Invalid configuration") + + # run orthanc + if Helpers.orthanc_under_tests_exe: + cls.launch_orthanc_exe( + exe_path=Helpers.orthanc_under_tests_exe, + config_path=config_path + ) + elif Helpers.orthanc_under_tests_docker_image: + cls.launch_orthanc_docker( + docker_image=Helpers.orthanc_under_tests_docker_image, + storage_name=storage_name, + config_name=config_name, + config_path=config_path + ) + else: + raise RuntimeError("Invalid configuration, can not launch Orthanc") + + @classmethod + def launch_orthanc_exe(cls, exe_path: str, config_path: str): cls._orthanc_process = subprocess.Popen( [exe_path, "--verbose", config_path], stdout=subprocess.PIPE, @@ -131,8 +186,42 @@ raise RuntimeError(f"Orthanc failed to start '{exe_path}', conf = '{config_path}'. Check output above") @classmethod + def launch_orthanc_docker(cls, docker_image: str, storage_name: str, config_path: str, config_name: str): + + cmd = [ + "docker", "run", "--rm", + "-e", "VERBOSE_ENABLED=true", + "-e", "VERBOSE_STARTUP=true", + "-v", f"{config_path}:/etc/orthanc/orthanc.json", + "-v", f"{storage_name}:/var/lib/orthanc/db/", + "--name", config_name, + "-p", f"{Helpers.orthanc_under_tests_http_port}:{Helpers.orthanc_under_tests_http_port}", + "-p", f"{Helpers.orthanc_under_tests_dicom_port}:{Helpers.orthanc_under_tests_dicom_port}", + docker_image + ] + cls._orthanc_container_name = config_name + print("docker cmd line: " + " ".join(cmd)) + + cls._orthanc_process = subprocess.Popen( + cmd, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE + ) + + cls.o.wait_started(10) + if not cls.o.is_alive(): + output = cls.get_orthanc_process_output() + print("Orthanc output\n" + output) + + raise RuntimeError(f"Orthanc failed to start Orthanc through Docker '{docker_image}', conf = '{config_path}'. Check output above") + + + @classmethod def kill_orthanc(cls): - cls._orthanc_process.kill() + if Helpers.is_exe(): + cls._orthanc_process.kill() + else: + subprocess.run(["docker", "stop", cls._orthanc_container_name]) output = cls.get_orthanc_process_output() print("Orthanc output\n" + output) cls._orthanc_process = None diff -r 4ee85b016a40 -r 6917a26881ed NewTests/main.py --- a/NewTests/main.py Sat Apr 30 19:38:34 2022 +0200 +++ b/NewTests/main.py Mon May 02 17:05:42 2022 +0200 @@ -5,7 +5,7 @@ import argparse from helpers import Helpers import pathlib -# python3 main.py --orthanc_under_tests_exe=/home/alain/o/build/orthanc/Orthanc --pattern=Housekeeper.test_housekeeper.TestHousekeeper.*test_is* --plugin=/home/alain/o/build/orthanc/libHousekeeper.so +# python3 main.py --orthanc_under_tests_exe=/home/alain/o/build/orthanc/Orthanc --pattern=Housekeeper.test_housekeeper.TestHousekeeper.* --plugin=/home/alain/o/build/orthanc/libHousekeeper.so here = pathlib.Path(__file__).parent.resolve() @@ -23,7 +23,8 @@ parser.add_argument('--orthanc_under_tests_http_port', type=int, default=8042, help="orthanc under tests HTTP port") parser.add_argument('--orthanc_under_tests_exe', type=str, default=None, help="path to the orthanc executable (if it must be launched by this script)") parser.add_argument('--orthanc_previous_version_exe', type=str, default=None, help="path to the orthanc executable used to prepare previous version of storage/db (if it must be launched by this script and if different from orthanc_under_tests_exe)") - parser.add_argument('--orthanc_under_tests_docker_image', type=str, default=None, help="tag of the Docker image of the orthanc under tests (if it must be launched by this script)") + parser.add_argument('--orthanc_under_tests_docker_image', type=str, default=None, help="Docker image of the orthanc under tests (if it must be launched by this script)") + parser.add_argument('--orthanc_previous_version_docker_image', type=str, default=None, help="Docker image of the orthanc version used to prepare previous version of storage/db (if it must be launched by this script)") parser.add_argument('--skip_preparation', action='store_true', help="if this is a multi stage tests with preparations, skip the preparation") parser.add_argument('--break_after_preparation', action='store_true', help="if this is a multi stage tests with preparations, pause after the preparation (such that you can start your own orthanc-under-tests in your debugger)") parser.add_argument('-p', '--plugin', dest='plugins', action='append', type=str, help='path to a plugin to add to configuration') @@ -36,14 +37,21 @@ Helpers.orthanc_under_tests_hostname = args.orthanc_under_tests_hostname Helpers.orthanc_under_tests_http_port = args.orthanc_under_tests_http_port + Helpers.plugins = args.plugins + Helpers.orthanc_under_tests_exe = args.orthanc_under_tests_exe - Helpers.plugins = args.plugins + Helpers.orthanc_under_tests_docker_image = args.orthanc_under_tests_docker_image + if args.orthanc_previous_version_exe: Helpers.orthanc_previous_version_exe = args.orthanc_previous_version_exe else: Helpers.orthanc_previous_version_exe = args.orthanc_under_tests_exe - Helpers.orthanc_under_tests_docker_image = args.orthanc_under_tests_docker_image + if args.orthanc_previous_version_docker_image: + Helpers.orthanc_previous_version_docker_image = args.orthanc_previous_version_docker_image + else: + Helpers.orthanc_previous_version_docker_image = args.orthanc_under_tests_docker_image + if args.skip_preparation: Helpers.skip_preparation = True if args.break_after_preparation: