changeset 474:6917a26881ed

NewTests working with Docker
author Alain Mazy <am@osimis.io>
date Mon, 02 May 2022 17:05:42 +0200
parents 4ee85b016a40
children fe37cf5e9c02
files NewTests/Housekeeper/test_housekeeper.py NewTests/README NewTests/helpers.py NewTests/main.py
diffstat 4 files changed, 133 insertions(+), 25 deletions(-) [+]
line wrap: on
line diff
--- 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')
--- 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:
 -----------
 
--- 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
--- 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: