Skip to content

Commit 4ebef43

Browse files
authored
Supporting unstable versions and more robust testing configuration (#348)
1 parent 89215f2 commit 4ebef43

File tree

6 files changed

+126
-33
lines changed

6 files changed

+126
-33
lines changed

src/ansys/geometry/core/connection/__init__.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,14 @@
77
tess_to_pd,
88
unit_vector_to_grpc_direction,
99
)
10-
from ansys.geometry.core.connection.defaults import DEFAULT_HOST, DEFAULT_PORT
10+
from ansys.geometry.core.connection.defaults import (
11+
DEFAULT_HOST,
12+
DEFAULT_PORT,
13+
GEOMETRY_SERVICE_DOCKER_IMAGE,
14+
)
1115
from ansys.geometry.core.connection.launcher import (
1216
launch_local_modeler,
1317
launch_modeler,
1418
launch_remote_modeler,
1519
)
16-
from ansys.geometry.core.connection.localinstance import LocalDockerInstance
20+
from ansys.geometry.core.connection.localinstance import GeometryContainers, LocalDockerInstance

src/ansys/geometry/core/connection/client.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,11 @@ def log(self) -> PyGeometryCustomAdapter:
138138
"""Specific instance logger."""
139139
return self._log
140140

141+
@property
142+
def is_closed(self) -> bool:
143+
"""Checks if the client connection is closed or not."""
144+
return self._closed
145+
141146
@property
142147
def healthy(self) -> bool:
143148
"""Check if the client channel if healthy."""

src/ansys/geometry/core/connection/localinstance.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,10 @@
1515
class GeometryContainers(Enum):
1616
"""Provides an enum holding the different Geometry services available."""
1717

18-
WINDOWS_LATEST_STABLE = 0, "windows", "windows-latest"
19-
LINUX_LATEST_STABLE = 1, "linux", None
18+
WINDOWS_LATEST = 0, "windows", "windows-latest"
19+
LINUX_LATEST = 1, "linux", "linux-latest"
20+
WINDOWS_LATEST_UNSTABLE = 0, "windows", "windows-latest-unstable"
21+
LINUX_LATEST_UNSTABLE = 1, "linux", "linux-latest-unstable"
2022

2123

2224
class LocalDockerInstance:

src/ansys/geometry/core/modeler.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,10 @@ def create_design(self, name: str) -> "Design":
9999
self._designs.append(design)
100100
return self._designs[-1]
101101

102+
def close(self) -> None:
103+
"""``Modeler`` easy-access method to the client's ``close()`` method."""
104+
return self.client.close()
105+
102106
def __repr__(self):
103107
"""String representation of the modeler."""
104108
lines = []

tests/integration/conftest.py

Lines changed: 59 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,65 @@
1616
import pyvista as pv
1717

1818
from ansys.geometry.core import Modeler
19+
from ansys.geometry.core.connection.defaults import GEOMETRY_SERVICE_DOCKER_IMAGE
20+
from ansys.geometry.core.connection.localinstance import GeometryContainers, LocalDockerInstance
1921

2022
pv.OFF_SCREEN = True
2123

2224

2325
@pytest.fixture(scope="session")
24-
def modeler():
26+
def docker_instance():
27+
# This will only have a value in case that:
28+
#
29+
# 1) Docker is installed
30+
# 2) At least one of the Geometry Service images for your OS is downloaded
31+
# on the machine
32+
#
33+
local_instance = None
34+
35+
# Check 1)
36+
if LocalDockerInstance.is_docker_installed():
37+
# First of all let's get the Docker Engine OS
38+
docker_os = LocalDockerInstance.docker_client().info()["OSType"]
39+
is_image_available = False
40+
is_image_available_cont = None
41+
42+
# Now, let's get the OS-related images
43+
list_images = []
44+
list_containers = []
45+
for geom_service in GeometryContainers:
46+
if geom_service.value[1] == docker_os:
47+
list_images.append(f"{GEOMETRY_SERVICE_DOCKER_IMAGE}:{geom_service.value[2]}")
48+
list_containers.append(geom_service)
49+
50+
# Now, check 2)
51+
#
52+
available_images = LocalDockerInstance.docker_client().images.list(
53+
name=GEOMETRY_SERVICE_DOCKER_IMAGE
54+
)
55+
for image in available_images:
56+
for geom_image, geom_cont in zip(list_images, list_containers):
57+
if geom_image in image.tags:
58+
is_image_available = True
59+
is_image_available_cont = geom_cont
60+
break
61+
62+
if is_image_available:
63+
break
64+
65+
# Declare a LocalDockerInstance object if all checks went through
66+
if is_image_available:
67+
local_instance = LocalDockerInstance(
68+
connect_to_existing_service=True,
69+
restart_if_existing_service=True,
70+
image=is_image_available_cont,
71+
)
72+
73+
return local_instance
2574

75+
76+
@pytest.fixture(scope="session")
77+
def modeler(docker_instance):
2678
# Log to file - accepts str or Path objects, Path is passed for testing/coverage purposes.
2779
log_file_path = Path(__file__).absolute().parent / "logs" / "integration_tests_logs.txt"
2880

@@ -31,13 +83,15 @@ def modeler():
3183
except OSError:
3284
pass
3385

34-
modeler = Modeler(logging_level=logging.DEBUG, logging_file=log_file_path)
86+
modeler = Modeler(
87+
local_instance=docker_instance, logging_level=logging.DEBUG, logging_file=log_file_path
88+
)
3589

3690
yield modeler
3791

38-
# TODO: check cleanup on exit
39-
# modeler.exit()
40-
# assert modeler._client.closed
92+
# Cleanup on exit
93+
modeler.close()
94+
assert modeler.client.is_closed
4195

4296

4397
@pytest.fixture(scope="session", autouse=True)

tests/integration/test_launcher_local.py

Lines changed: 48 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,43 @@
11
"""Testing module for the local launcher."""
22

3+
import re
4+
35
import pytest
46

57
from ansys.geometry.core import Modeler
68
from ansys.geometry.core.connection import LocalDockerInstance, launch_local_modeler
79

810

11+
def _check_no_shutdown_warning(port: int, log: str) -> bool:
12+
msg = f"WARNING localhost:{port}:client\.py:[0-9]+ Geometry Service will not be shutdown since it was already running\.\.\." # noqa : E501
13+
pattern = re.compile(msg)
14+
return True if pattern.search(log) else False
15+
16+
17+
def _check_service_already_running(port: int, log: str) -> bool:
18+
msg = f"WARNING PyGeometry_global:localinstance\.py:[0-9]+ Service already running at port {port}\.\.\." # noqa : E501
19+
pattern = re.compile(msg)
20+
return True if pattern.search(log) else False
21+
22+
23+
def _check_restarting_service(port: int, log: str) -> bool:
24+
msg = f"WARNING PyGeometry_global:localinstance\.py:124 Restarting service already running at port {port}\.\.\." # noqa : E501
25+
pattern = re.compile(msg)
26+
return True if pattern.search(log) else False
27+
28+
929
def test_if_docker_is_installed():
1030
"""Simple test to check if Docker is installed in the machine."""
1131
assert LocalDockerInstance.is_docker_installed()
1232

1333

14-
def test_local_launcher_connect(modeler: Modeler, caplog: pytest.LogCaptureFixture):
34+
def test_local_launcher_connect(
35+
modeler: Modeler, caplog: pytest.LogCaptureFixture, docker_instance: LocalDockerInstance
36+
):
1537
"""Checking connection to existing service using launch modeler."""
38+
if not docker_instance:
39+
pytest.skip("Docker local launcher tests are not runnable.")
40+
1641
# Get the existing target
1742
target = modeler.client.target().split(":")
1843
port = int(target[1])
@@ -25,20 +50,23 @@ def test_local_launcher_connect(modeler: Modeler, caplog: pytest.LogCaptureFixtu
2550
local_modeler = launch_local_modeler(
2651
port=port, connect_to_existing_service=True, restart_if_existing_service=False
2752
)
28-
29-
msg = f"WARNING PyGeometry_global:localinstance.py:155 Service already running at port {port}...\n" # noqa : E501
30-
assert msg in caplog.text
53+
assert _check_service_already_running(port, caplog.text) is True
54+
caplog.clear()
3155

3256
# Try to close it... this will throw a warning
3357
local_modeler.client.close()
34-
35-
msg = f"WARNING localhost:{port}:client.py:182 Geometry Service will not be shutdown since it was already running...\n" # noqa : E501
36-
assert msg in caplog.text
58+
assert _check_no_shutdown_warning(port, caplog.text) is True
59+
caplog.clear()
3760

3861

39-
def test_local_launcher_connect_with_restart(modeler: Modeler, caplog: pytest.LogCaptureFixture):
62+
def test_local_launcher_connect_with_restart(
63+
modeler: Modeler, caplog: pytest.LogCaptureFixture, docker_instance: LocalDockerInstance
64+
):
4065
"""Checking connection to existing service using launch modeler and
4166
restarting existing service."""
67+
if not docker_instance:
68+
pytest.skip("Docker local launcher tests are not runnable.")
69+
4270
# Get the existing target
4371
target = modeler.client.target().split(":")
4472
port = int(target[1])
@@ -50,8 +78,7 @@ def test_local_launcher_connect_with_restart(modeler: Modeler, caplog: pytest.Lo
5078
)
5179

5280
# Check that the warning is NOT raised
53-
msg = f"WARNING PyGeometry_global:localinstance.py:155 Service already running at port {new_port}...\n" # noqa : E501
54-
assert msg not in caplog.text
81+
assert _check_service_already_running(new_port, caplog.text) is False
5582
caplog.clear()
5683

5784
# Connect to the previous modeler and restart it
@@ -60,30 +87,30 @@ def test_local_launcher_connect_with_restart(modeler: Modeler, caplog: pytest.Lo
6087
)
6188

6289
# Check that the warnings are raised
63-
msg = f"WARNING PyGeometry_global:localinstance.py:155 Service already running at port {new_port}...\n" # noqa : E501
64-
assert msg in caplog.text
65-
msg = f"WARNING PyGeometry_global:localinstance.py:122 Restarting service already running at port {new_port}...\n" # noqa : E501
66-
assert msg in caplog.text
90+
assert _check_service_already_running(new_port, caplog.text) is True
91+
assert _check_restarting_service(new_port, caplog.text) is True
6792
caplog.clear()
6893

6994
# Try to close the new_modeler_restarted... this will throw a warning
7095
new_modeler_restarted.client.close()
7196

72-
msg = f"WARNING localhost:{new_port}:client.py:182 Geometry Service will not be shutdown since it was already running...\n" # noqa : E501
73-
assert msg in caplog.text
97+
assert _check_no_shutdown_warning(new_port, caplog.text) is True
7498
caplog.clear()
7599

76100
# And now try to close the new_modeler... this will NOT throw a warning
77101
new_modeler.client.close()
78102

79-
msg = f"WARNING localhost:{new_port}:client.py:182 Geometry Service will not be shutdown since it was already running...\n" # noqa : E501
80-
assert msg not in caplog.text
103+
assert _check_no_shutdown_warning(new_port, caplog.text) is False
81104
caplog.clear()
82105

83106

84-
def test_try_deploying_container_with_same_name(modeler: Modeler, caplog: pytest.LogCaptureFixture):
107+
def test_try_deploying_container_with_same_name(
108+
modeler: Modeler, caplog: pytest.LogCaptureFixture, docker_instance: LocalDockerInstance
109+
):
85110
"""Checks that an error is raised when trying to deploy a container
86111
with a name that already exists."""
112+
if not docker_instance:
113+
pytest.skip("Docker local launcher tests are not runnable.")
87114

88115
# Get the existing target
89116
target = modeler.client.target().split(":")
@@ -101,8 +128,7 @@ def test_try_deploying_container_with_same_name(modeler: Modeler, caplog: pytest
101128
)
102129

103130
# Check that the warning is NOT raised
104-
msg = f"WARNING PyGeometry_global:localinstance.py:155 Service already running at port {new_port}...\n" # noqa : E501
105-
assert msg not in caplog.text
131+
assert _check_service_already_running(new_port, caplog.text) is False
106132
caplog.clear()
107133

108134
# Now try launching a service in a new port (where no service is available) but
@@ -119,7 +145,5 @@ def test_try_deploying_container_with_same_name(modeler: Modeler, caplog: pytest
119145

120146
# And now try to close the new_modeler... this will NOT throw a warning
121147
new_modeler.client.close()
122-
123-
msg = f"WARNING localhost:{new_port}:client.py:182 Geometry Service will not be shutdown since it was already running...\n" # noqa : E501
124-
assert msg not in caplog.text
148+
assert _check_no_shutdown_warning(new_port, caplog.text) is False
125149
caplog.clear()

0 commit comments

Comments
 (0)