diff --git a/test/integ/test_houdini_adaptors.py b/test/integ/test_houdini_adaptors.py index 604eb8f..82f2a77 100644 --- a/test/integ/test_houdini_adaptors.py +++ b/test/integ/test_houdini_adaptors.py @@ -6,6 +6,10 @@ from .helpers.test_runners import run_command, run_houdini_adaptor_test from .helpers.image_comparison import assert_all_images_close +import os +import psutil + +from deadline.houdini_adaptor.HoudiniAdaptor import HoudiniAdaptor @pytest.mark.adaptor @@ -91,3 +95,150 @@ def test_render_dependencies_adaptor( assert_all_images_close( script_location / "render_dependencies_test" / "expected_images", tmp_path ) + + def test_adaptor_open_close( + self, hython_location: Path, script_location: Path, tmp_path: Path + ) -> None: + """Test that the adaptor can successfully open and close the Houdini client.""" + run_command( + [ + str(hython_location), + str(script_location / "minimal_test" / "_test_hip.py"), + "--", + str(script_location), + str(tmp_path), + "adaptor", + ] + ) + + adaptor = HoudiniAdaptor( + { + "scene_file": f"{str(tmp_path)}/test.hip", + "render_node": "/out/mantra1", + "version": os.environ["HOUDINI_VERSION"], + } + ) + + adaptor.on_start() + assert adaptor._houdini_is_running + + # Validate process is actually running using PID + assert adaptor._houdini_client + pid = adaptor._houdini_client.pid + assert psutil.pid_exists(pid) + + adaptor.on_cleanup() + assert not adaptor._houdini_is_running + assert not psutil.pid_exists(pid) + + def test_adaptor_cancel_closes_houdini( + self, hython_location: Path, script_location: Path, tmp_path: Path + ) -> None: + """Test that on_cancel closes the Houdini client.""" + run_command( + [ + str(hython_location), + str(script_location / "minimal_test" / "_test_hip.py"), + "--", + str(script_location), + str(tmp_path), + "adaptor", + ] + ) + + adaptor = HoudiniAdaptor( + { + "scene_file": f"{str(tmp_path)}/test.hip", + "render_node": "/out/mantra1", + "version": os.environ["HOUDINI_VERSION"], + } + ) + + adaptor.on_start() + assert adaptor._houdini_is_running + + assert adaptor._houdini_client + pid = adaptor._houdini_client.pid + assert psutil.pid_exists(pid) + + adaptor.on_cancel() + assert not adaptor._houdini_is_running + assert not psutil.pid_exists(pid) + + def test_adaptor_daemon_open_close( + self, hython_location: Path, script_location: Path, tmp_path: Path + ) -> None: + """Test that the adaptor can open and close the Houdini client in daemon mode.""" + import tempfile + import subprocess + import json + import time + + run_command( + [ + str(hython_location), + str(script_location / "minimal_test" / "_test_hip.py"), + "--", + str(script_location), + str(tmp_path), + "adaptor", + ] + ) + + with tempfile.TemporaryDirectory() as tmpdir: + connection_file = Path(tmpdir) / "connection.json" + + # Start daemon backend + init_data = { + "scene_file": f"{str(tmp_path)}/test.hip", + "render_node": "/out/mantra1", + "version": os.environ["HOUDINI_VERSION"], + } + + try: + start_process = subprocess.run( + [ + "houdini-openjd", + "daemon", + "start", + "--connection-file", + str(connection_file), + "--init-data", + json.dumps(init_data), + ] + ) + + assert start_process.returncode == 0 + + # Wait for connection file + timeout = time.time() + 10 + while not connection_file.exists() and time.time() < timeout: + time.sleep(0.1) + assert connection_file.exists() + + # Connect and verify process is running + connection_data = json.loads(connection_file.read_text()) + assert "socket" in connection_data, "Connection file should contain socket" + + finally: + # Stop daemon + if connection_file.exists(): + stop_cmd = [ + "houdini-openjd", + "daemon", + "stop", + "--connection-file", + str(connection_file), + ] + + stop_process = subprocess.run( + stop_cmd, + capture_output=True, + text=True, + timeout=30, + ) + + # Verify daemon stopped successfully + assert ( + stop_process.returncode == 0 + ), f"Daemon stop failed: {stop_process.stderr}"