Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

adding integration tests in tests directory #359

Merged
merged 6 commits into from
May 3, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -187,8 +187,21 @@ jobs:
- name: Install pyfluent with post requirements
run: make install-post

- name: Login to GitHub Container Registry
uses: docker/login-action@v1
with:
registry: ghcr.io
username: ${{ secrets.GH_USERNAME }}
password: ${{ secrets.REPO_DOWNLOAD_PAT }}

- name: Pull Fluent docker image
run: make docker-pull

- name: Unit Testing
run: make unittest
env:
ANSYSLMD_LICENSE_FILE: ${{ format('1055@{0}', secrets.LICENSE_SERVER) }}
PYFLUENT_START_INSTANCE: 0

- name: Upload Coverage Results
uses: actions/upload-artifact@v2
Expand Down
3 changes: 3 additions & 0 deletions src/ansys/fluent/core/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -86,3 +86,6 @@ def disable_logging_to_file() -> None:

except:
pass

BUILDING_GALLERY = False
RUNNING_PYTEST = False
78 changes: 78 additions & 0 deletions src/ansys/fluent/core/launcher/fluent_container.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
import os
import socket
import subprocess
import tempfile
import time
from typing import List


def _get_free_port() -> int:
sock = socket.socket()
sock.bind(("", 0))
return sock.getsockname()[1]


def start_fluent_container(mounted_from: str, mounted_to: str, args: List[str]) -> int:
"""Start a Fluent container.

Parameters
----------
mounted_from : str
Path to mount from. ``mounted_from`` will be mounted as ``mount_to``
within the container.
mounted_to : str
Path to mount to. ``mounted_from`` will be mounted as ``mount_to``
within the container.
args : List[str]
List of Fluent launch arguments

Returns
-------
int
gPRC server port exposed from container
"""
fd, sifile = tempfile.mkstemp(suffix=".txt", prefix="serverinfo-", dir=mounted_from)
os.close(fd)
timeout = 100
license_server = os.environ["ANSYSLMD_LICENSE_FILE"]
port = _get_free_port()

try:
subprocess.run(
[
"docker",
"run",
"-d",
"--rm",
"-p",
f"{port}:{port}",
"-v",
f"{mounted_from}:{mounted_to}",
"-e",
f"ANSYSLMD_LICENSE_FILE={license_server}",
"-e",
f"REMOTING_PORTS={port}/portspan=2",
"-e",
"FLUENT_LAUNCHED_FROM_PYFLUENT=1",
"ghcr.io/pyansys/pyfluent",
"-g",
f"-sifile={sifile}",
]
+ args
)

sifile_last_mtime = os.stat(sifile).st_mtime
while True:
if os.stat(sifile).st_mtime > sifile_last_mtime:
time.sleep(1)
break
if timeout == 0:
break
time.sleep(1)
timeout -= 1
return port
except OSError:
pass
finally:
if os.path.exists(sifile):
os.remove(sifile)
108 changes: 66 additions & 42 deletions src/ansys/fluent/core/launcher/launcher.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
import time
from typing import Any, Dict

from ansys.fluent.core.launcher.fluent_container import start_fluent_container
from ansys.fluent.core.session import Session
from ansys.fluent.core.utils.logging import LOG

Expand Down Expand Up @@ -63,6 +64,55 @@ def _get_subprocess_kwargs_for_fluent(env: Dict[str, Any]) -> Dict[str, Any]:
return kwargs


def _build_fluent_launch_args_string(**kwargs) -> str:
"""Build Fluent's launch arguments string from keyword arguments.
Returns
-------
str
Fluent's launch arguments string
"""
all_options = None
with open(_OPTIONS_FILE, encoding="utf-8") as fp:
all_options = json.load(fp)
launch_args_string = ""
for k, v in all_options.items():
argval = kwargs.get(k)
default = v.get("default")
if argval is None and v.get("required") is True:
argval = default
if argval is not None:
allowed_values = v.get("allowed_values")
if allowed_values and argval not in allowed_values:
if default is not None:
old_argval = argval
argval = default
LOG.warning(
"Default value %s is chosen for %s as the passed "
"value %s is outside allowed values %s.",
argval,
k,
old_argval,
allowed_values,
)
else:
LOG.warning(
"%s = %s is discarded as it is outside " "allowed values %s.",
k,
argval,
allowed_values,
)
continue
fluent_map = v.get("fluent_map")
if fluent_map:
if isinstance(argval, str):
json_key = argval
else:
json_key = json.dumps(argval)
argval = fluent_map[json_key]
launch_args_string += v["fluent_format"].replace("{}", str(argval))
return launch_args_string


# pylint: disable=unused-argument
def launch_fluent(
version: str = None,
Expand Down Expand Up @@ -144,45 +194,7 @@ def launch_fluent(
if start_instance:
exe_path = _get_fluent_exe_path()
launch_string = exe_path
all_options = None
with open(_OPTIONS_FILE, encoding="utf-8") as fp:
all_options = json.load(fp)
for k, v in all_options.items():
argval = argvals.get(k)
default = v.get("default")
if argval is None and v.get("required") is True:
argval = default
if argval is not None:
allowed_values = v.get("allowed_values")
if allowed_values and argval not in allowed_values:
if default is not None:
old_argval = argval
argval = default
LOG.warning(
"Default value %s is chosen for %s as the passed "
"value %s is outside allowed values %s.",
argval,
k,
old_argval,
allowed_values,
)
else:
LOG.warning(
"%s = %s is discarded as it is outside "
"allowed values %s.",
k,
argval,
allowed_values,
)
continue
fluent_map = v.get("fluent_map")
if fluent_map:
if isinstance(argval, str):
json_key = argval
else:
json_key = json.dumps(argval)
argval = fluent_map[json_key]
launch_string += v["fluent_format"].replace("{}", str(argval))
launch_string += _build_fluent_launch_args_string(**argvals)
server_info_filepath = _get_server_info_filepath()
try:
launch_string += f" {additional_arguments}"
Expand Down Expand Up @@ -218,6 +230,18 @@ def launch_fluent(
if server_info_file.exists():
server_info_file.unlink()
else:
ip = argvals.get("ip", None)
port = argvals.get("port", None)
return Session(ip=ip, port=port, cleanup_on_exit=cleanup_on_exit)
import ansys.fluent.core as pyfluent

if pyfluent.BUILDING_GALLERY or pyfluent.RUNNING_PYTEST:
args = _build_fluent_launch_args_string(**argvals).split()
# Assumes the container OS will be able to create the
# EXAMPLES_PATH of host OS. With the Fluent docker
# container, the following currently works only in linux.
port = start_fluent_container(
pyfluent.EXAMPLES_PATH, pyfluent.EXAMPLES_PATH, args
)
return Session(port=port, cleanup_on_exit=cleanup_on_exit)
else:
ip = argvals.get("ip", None)
port = argvals.get("port", None)
return Session(ip=ip, port=port, cleanup_on_exit=cleanup_on_exit)
8 changes: 8 additions & 0 deletions tests/conftest.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import pytest

import ansys.fluent.core as pyfluent


@pytest.fixture
def with_running_pytest(monkeypatch: pytest.MonkeyPatch) -> None:
monkeypatch.setattr(pyfluent, "RUNNING_PYTEST", True)
Loading