Skip to content

Commit 9ba6307

Browse files
test: add more tests to expand coverage (#2087)
Co-authored-by: pyansys-ci-bot <92810346+pyansys-ci-bot@users.noreply.github.com>
1 parent 8572519 commit 9ba6307

File tree

4 files changed

+620
-7
lines changed

4 files changed

+620
-7
lines changed

doc/changelog.d/2087.test.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Add more tests to expand coverage

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

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -561,13 +561,14 @@ def _is_port_available(port: int, host: str = "localhost") -> bool:
561561
The optional argument is the ip address where to check port availability.
562562
Its default is ``localhost``.
563563
"""
564-
if port != 0:
565-
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock:
566-
try:
567-
sock.bind((host, port))
568-
return True
569-
except socket.error:
570-
return False
564+
if port == 0:
565+
return False # Port 0 is reserved and cannot be used directly.
566+
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock:
567+
try:
568+
sock.bind((host, port))
569+
return True
570+
except socket.error:
571+
return False
571572

572573

573574
def _manifest_path_provider(

tests/test_connection.py

Lines changed: 197 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@
2121
# SOFTWARE.
2222

2323
import os
24+
import socket
25+
import tempfile
2426

2527
from beartype.roar import BeartypeCallHintParamViolation
2628
import grpc
@@ -44,6 +46,11 @@
4446
)
4547
from ansys.geometry.core.connection.product_instance import (
4648
ProductInstance,
49+
_check_minimal_versions,
50+
_check_port_or_get_one,
51+
_get_common_env,
52+
_is_port_available,
53+
_manifest_path_provider,
4754
prepare_and_start_backend,
4855
)
4956
from ansys.geometry.core.math import Frame, Plane, Point2D, Point3D, UnitVector3D
@@ -417,3 +424,193 @@ def test_prepare_and_start_backend_invalid_version():
417424
backend_type=BackendType.WINDOWS_SERVICE,
418425
version="invalid_version", # Pass a non-integer value for version
419426
)
427+
428+
429+
def test_is_port_available():
430+
"""Test that _is_port_available correctly detects available and unavailable ports."""
431+
host = "localhost"
432+
433+
# Test an available port
434+
available_port = 5000
435+
assert _is_port_available(available_port, host) is True
436+
437+
# Test an unavailable port by binding it
438+
unavailable_port = 5001
439+
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
440+
s.bind((host, unavailable_port)) # Bind the port to make it unavailable
441+
assert _is_port_available(unavailable_port, host) is False
442+
443+
# Test port 0 (invalid port)
444+
assert _is_port_available(0, host) is False
445+
446+
447+
def test_manifest_path_exists(tmp_path):
448+
"""Test when the manifest path exists."""
449+
# Create a temporary manifest file
450+
manifest_path = tmp_path / "test_manifest.xml"
451+
manifest_path.touch() # Create the file
452+
453+
# Call the function
454+
result = _manifest_path_provider(
455+
version=241, available_installations={}, manifest_path=str(manifest_path)
456+
)
457+
458+
# Assert the returned path is the same as the input
459+
assert result == str(manifest_path)
460+
461+
462+
def test_manifest_path_does_not_exist(tmp_path, caplog):
463+
"""Test when the manifest path does not exist and handle RuntimeError."""
464+
465+
# Define a non-existent manifest path
466+
manifest_path = tmp_path / "non_existent_manifest.xml"
467+
468+
# Provide a valid `available_installations` dictionary with the required version key
469+
available_installations = {241: str(tmp_path)}
470+
471+
# Simulate the default manifest file path
472+
default_manifest_path = tmp_path / "Addins" / "ApiServer" / "manifest.xml"
473+
default_manifest_path.parent.mkdir(
474+
parents=True, exist_ok=True
475+
) # Create the directory structure
476+
477+
# Ensure the default manifest file does not exist
478+
assert not default_manifest_path.exists()
479+
480+
# Call the function and expect a RuntimeError
481+
with pytest.raises(RuntimeError, match="Default manifest file's path does not exist."):
482+
_manifest_path_provider(
483+
version=241,
484+
available_installations=available_installations,
485+
manifest_path=str(manifest_path),
486+
)
487+
488+
# Assert the warning message is logged
489+
assert (
490+
"Specified manifest file's path does not exist. Taking install default path." in caplog.text
491+
)
492+
493+
494+
@pytest.mark.parametrize(
495+
"latest_installed_version, specific_minimum_version, should_raise, expected_message",
496+
[
497+
(
498+
240,
499+
None,
500+
True,
501+
"PyAnsys Geometry is compatible with Ansys Products from version 24.1.0.",
502+
),
503+
(242, None, False, None),
504+
(250, 251, True, "PyAnsys Geometry is compatible with Ansys Products from version 25.1.0."),
505+
(252, 251, False, None),
506+
],
507+
)
508+
def test_check_minimal_versions(
509+
latest_installed_version, specific_minimum_version, should_raise, expected_message
510+
):
511+
"""Test _check_minimal_versions with various scenarios."""
512+
if should_raise:
513+
with pytest.raises(SystemError, match=expected_message):
514+
_check_minimal_versions(latest_installed_version, specific_minimum_version)
515+
else:
516+
try:
517+
_check_minimal_versions(latest_installed_version, specific_minimum_version)
518+
except SystemError:
519+
pytest.fail("SystemError raised unexpectedly.")
520+
521+
522+
@pytest.mark.parametrize(
523+
"port, should_raise, expected_message",
524+
[
525+
(5000, False, None), # Test for an available port
526+
(
527+
5001,
528+
True,
529+
"Port 5001 is already in use. Please specify a different one.",
530+
), # Test for an unavailable port
531+
],
532+
)
533+
def test_check_port_or_get_one(port, should_raise, expected_message):
534+
"""Test _check_port_or_get_one with various port availability scenarios."""
535+
host = "localhost"
536+
537+
if should_raise:
538+
# Bind the port to make it unavailable
539+
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
540+
s.bind((host, port))
541+
s.listen(1) # Start listening on the port
542+
543+
# Call the function and expect a ConnectionError
544+
with pytest.raises(ConnectionError, match=expected_message):
545+
_check_port_or_get_one(port)
546+
else:
547+
# Ensure the port is available
548+
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
549+
assert s.connect_ex((host, port)) != 0 # Port should not be in use
550+
551+
# Call the function
552+
result = _check_port_or_get_one(port)
553+
554+
# Assert the returned port is the same as the input
555+
assert result == port
556+
557+
558+
@pytest.mark.parametrize(
559+
"host, port, enable_trace, server_log_level, server_logs_folder, expected_env",
560+
[
561+
(
562+
"127.0.0.1",
563+
8080,
564+
True,
565+
2,
566+
None, # Use a dynamically created temporary directory
567+
{
568+
"API_ADDRESS": "127.0.0.1",
569+
"API_PORT": "8080",
570+
"LOG_LEVEL": "0", # Trace mode overrides log level to 0
571+
"ENABLE_TRACE": "1",
572+
},
573+
),
574+
(
575+
"localhost",
576+
9090,
577+
False,
578+
3,
579+
None,
580+
{
581+
"API_ADDRESS": "localhost",
582+
"API_PORT": "9090",
583+
"LOG_LEVEL": "3", # Log level remains unchanged
584+
},
585+
),
586+
],
587+
)
588+
def test_get_common_env(
589+
host, port, enable_trace, server_log_level, server_logs_folder, expected_env
590+
):
591+
"""Test the _get_common_env function with various scenarios."""
592+
# Dynamically create a temporary directory for logs if server_logs_folder is None
593+
with tempfile.TemporaryDirectory() as temp_logs_folder:
594+
if server_logs_folder is None:
595+
server_logs_folder = temp_logs_folder
596+
597+
# Call the function
598+
env = _get_common_env(
599+
host=host,
600+
port=port,
601+
enable_trace=enable_trace,
602+
server_log_level=server_log_level,
603+
server_logs_folder=server_logs_folder,
604+
)
605+
606+
# Update expected_env with the dynamically created logs folder
607+
if enable_trace:
608+
expected_env["ANS_DSCO_REMOTE_LOGS_FOLDER"] = server_logs_folder
609+
610+
# Assert environment variables are correctly set
611+
for key, value in expected_env.items():
612+
assert env[key] == value
613+
614+
# Assert keys that should not exist in the environment
615+
if not enable_trace:
616+
assert "ENABLE_TRACE" not in env

0 commit comments

Comments
 (0)