Skip to content

Commit

Permalink
Merge branch 'main' into maint/activate_2d_meshing_tests_for_251
Browse files Browse the repository at this point in the history
  • Loading branch information
prmukherj authored Dec 20, 2024
2 parents f2ceade + e586c61 commit 3e3fa0c
Show file tree
Hide file tree
Showing 91 changed files with 4,119 additions and 2,775 deletions.
133 changes: 91 additions & 42 deletions .ci/fluent_test_runner.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
"""Script to run Fluent test in Docker container."""

import argparse
import concurrent.futures
import logging
import os
from pathlib import Path
Expand All @@ -21,11 +22,16 @@ class FluentRuntimeError(RuntimeError):
pass


def run_fluent_test(journal_file: Path, launcher_args: str = "") -> None:
"""Run Fluent test.
def _run_single_test(
src_test_dir: Path, journal_file: Path, launcher_args: str
) -> None:
"""Run a single Fluent test.
Parameters
----------
src_test_dir : Path
Path to the Fluent test directory in the host.
journal_file : Path
Absolute path to the journal file.
Expand All @@ -41,12 +47,27 @@ def run_fluent_test(journal_file: Path, launcher_args: str = "") -> None:
src_pyfluent_dir = str(Path(pyfluent.__file__).parent)
verion_for_file_name = FluentVersion.current_dev().number
dst_pyfluent_dir = f"/ansys_inc/v{verion_for_file_name}/commonfiles/CPython/3_10/linx64/Release/python/lib/python3.10/site-packages/ansys/fluent/core"
src_test_dir = str(journal_file.parent)
src_gen_dir = (
Path(pyfluent.__file__).parent / "ansys" / "fluent" / "core" / "generated"
)
dst_gen_dir = f"/ansys_inc/v{verion_for_file_name}/fluent/fluent{FluentVersion.current_dev()!r}/cortex/pylib/flapi/generated"
dst_test_dir = "/testing"
working_dir = Path(dst_test_dir)
parent = journal_file.parent
parents = []
while parent != src_test_dir:
parents.append(parent.name)
parent = parent.parent
parents.reverse()
for parent in parents:
working_dir /= parent
working_dir = str(working_dir)
src_test_dir = str(src_test_dir)
logging.debug(f"src_pyfluent_dir: {src_pyfluent_dir}")
logging.debug(f"dst_pyfluent_dir: {dst_pyfluent_dir}")
logging.debug(f"src_test_dir: {src_test_dir}")
logging.debug(f"dst_test_dir: {dst_test_dir}")
logging.debug(f"working_dir: {working_dir}")

docker_client = docker.from_env()
version_for_image_tag = FluentVersion.current_dev().docker_image_tag
Expand All @@ -55,34 +76,55 @@ def run_fluent_test(journal_file: Path, launcher_args: str = "") -> None:
image=image_name,
volumes=[
f"{src_pyfluent_dir}:{dst_pyfluent_dir}",
f"{src_gen_dir}:{dst_gen_dir}", # Try removing this after pyfluent is updated in commonfiles
f"{src_test_dir}:{dst_test_dir}",
],
working_dir=dst_test_dir,
working_dir=working_dir,
environment={"ANSYSLMD_LICENSE_FILE": os.environ["ANSYSLMD_LICENSE_FILE"]},
command=f"3ddp {launcher_args} -gu -py -i {journal_file.name}",
command=f"{launcher_args} -gu -py -i {journal_file.name}",
detach=True,
stdout=True,
stderr=True,
auto_remove=True,
)
while True:
container.reload()
if container.status == "exited":
break
stderr = container.logs(stdout=False, stderr=True)
if stderr:
stderr = stderr.decode()
for line in stderr.split("\n"):
if line.strip().startswith("Error:"):
if "Expected exception" in line: # for check_assert.py
container.stop()
else:
raise FluentRuntimeError(line)
sleep(1)
logging.debug(container.logs(stderr=True).decode())
container.remove()


MAX_TEST_PATH_LENGTH = 40
try:
while True:
container.reload()
if container.status == "exited":
break
stderr = container.logs(stdout=False, stderr=True)
if stderr:
stderr = stderr.decode()
for line in stderr.splitlines():
if line.strip().startswith("Error:"):
if "Expected exception" in line: # for check_assert.py
container.stop()
else:
raise FluentRuntimeError(stderr)
sleep(1)
print(container.logs(stderr=True).decode())
container.remove()
except docker.errors.DockerException:
pass


MAX_TEST_PATH_LENGTH = 100


def _run_single_test_with_status_print(
src_test_dir: Path, journal_file: Path, launcher_args: str, test_file_relpath: str
) -> bool:
try:
_run_single_test(src_test_dir, journal_file, launcher_args)
print(
f"{test_file_relpath}{(MAX_TEST_PATH_LENGTH + 10 - len(test_file_relpath)) * '·'}PASSED"
)
except FluentRuntimeError as e:
print(
f"{test_file_relpath}{(MAX_TEST_PATH_LENGTH + 10 - len(test_file_relpath)) * '·'}FAILED"
)
print(e)
return True


if __name__ == "__main__":
Expand All @@ -93,27 +135,34 @@ def run_fluent_test(journal_file: Path, launcher_args: str = "") -> None:
)
args = parser.parse_args()
test_dir = Path.cwd() / args.test_dir
with TemporaryDirectory(ignore_cleanup_errors=True) as tmpdir:
copytree(test_dir, tmpdir, dirs_exist_ok=True)
exception_occurred = False
for test_file in Path(tmpdir).rglob("*.py"):
with TemporaryDirectory(ignore_cleanup_errors=True) as src_test_dir:
copytree(test_dir, src_test_dir, dirs_exist_ok=True)
statuses = []
arguments = []
src_test_dir = Path(src_test_dir)
for test_file in (src_test_dir / "fluent").rglob("*.py"):
config_file = test_file.with_suffix(".yaml")
launcher_args = ""
if config_file.exists():
configs = yaml.safe_load(config_file.read_text())
launcher_args = configs.get("launcher_args", "")
test_file_relpath = str(test_file.relative_to(tmpdir))
print(f"Running {test_file_relpath}", end="", flush=True)
try:
run_fluent_test(test_file, launcher_args)
print(
f"{(MAX_TEST_PATH_LENGTH + 10 - len(test_file_relpath)) * '·'}PASSED"
)
except FluentRuntimeError as e:
print(
f"{(MAX_TEST_PATH_LENGTH + 10 - len(test_file_relpath)) * '·'}FAILED"
)
print(e)
exception_occurred = True
if exception_occurred:
test_file_relpath = str(test_file.relative_to(src_test_dir))
arguments.append(
(src_test_dir, test_file, launcher_args, test_file_relpath)
)
max_workers = int(os.getenv("MAX_WORKERS_FLUENT_TESTS", 4))
if max_workers > 1:
with concurrent.futures.ThreadPoolExecutor(
max_workers=max_workers
) as executor:
futures = [
executor.submit(_run_single_test_with_status_print, *args)
for args in arguments
]
for future in concurrent.futures.as_completed(futures):
statuses.append(future.result())
else:
for args in arguments:
statuses.append(_run_single_test_with_status_print(*args))
if any(statuses):
exit(1)
9 changes: 6 additions & 3 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -117,14 +117,16 @@ jobs:
- name: Install Quarto
uses: quarto-dev/quarto-actions/setup@v2
with:
tinytex: true


- name: Check Quarto Version
shell: bash
run: |
quarto --version
- name: Verify tinytex is installed
run: |
quarto install tinytex --no-prompt --update-path
- name: "Install Poppler for PDF to PNG conversion"
shell: bash
run: |
Expand Down Expand Up @@ -197,6 +199,7 @@ jobs:
make build-doc-source
env:
FLUENT_IMAGE_TAG: ${{ env.DOC_DEPLOYMENT_IMAGE_TAG }}
PYFLUENT_DOC_SKIP_CHEATSHEET: 1

- name: Zip HTML Documentation before upload
run: |
Expand Down
8 changes: 7 additions & 1 deletion .github/workflows/test-fluent-journals.yml
Original file line number Diff line number Diff line change
Expand Up @@ -82,4 +82,10 @@ jobs:
- name: Run Fluent tests
run: |
python .ci/fluent_test_runner.py tests/fluent
make write-and-run-fluent-tests
env:
MAX_WORKERS_FLUENT_TESTS: 1

- name: Cleanup previous docker containers
if: always()
run: make cleanup-previous-docker-containers
5 changes: 2 additions & 3 deletions .github/workflows/test-run-dev-version-nightly.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,14 @@ env:
PYFLUENT_WATCHDOG_DEBUG: 'OFF'
PYFLUENT_HIDE_LOG_SECRETS: 1
MAIN_PYTHON_VERSION: '3.10'
FLUENT_IMAGE_TAG: v25.2.0
FLUENT_VERSION: 252

jobs:
test:
name: Unit Testing
runs-on: [self-hosted, pyfluent]
timeout-minutes: 120
env:
FLUENT_IMAGE_TAG: v25.2.0
FLUENT_VERSION: 252

steps:
- uses: actions/checkout@v4
Expand Down
2 changes: 1 addition & 1 deletion .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ repos:
hooks:
- id: black
args: [
--target-version=py39
--target-version=py310
]

- repo: https://github.com/pycqa/isort
Expand Down
2 changes: 1 addition & 1 deletion CONTRIBUTORS.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,4 @@
* [Harshal Pohekar](https://github.com/hpohekar)
* [Mainak Kundu](https://github.com/mkundu1)
* [Prithwish Mukherjee](https://github.com/prmukherj)
* [Raphael Luciano](https://github.com/raph-luc)
* [Raphael Luciano](https://github.com/raph-luc)
10 changes: 8 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@ docker-pull:
test-import:
@python -c "import ansys.fluent.core as pyfluent"

PYTESTEXTRA = --cache-clear --cov=ansys.fluent --cov-report=xml:cov_xml.xml --cov-report=html
PYTESTRERUN = --last-failed --last-failed-no-failures none
PYTESTEXTRA = --cache-clear --cov=ansys.fluent --cov-report=xml:cov_xml.xml --cov-report=html -n 4
PYTESTRERUN = --last-failed --last-failed-no-failures none -n 4

unittest: unittest-dev-242

Expand Down Expand Up @@ -179,3 +179,9 @@ cleanup-previous-docker-containers:
docker stop $(docker ps -a -q); \
fi
@if [ -n "$(docker ps -a -q)" ]; then docker rm -vf $(docker ps -a -q); fi

write-and-run-fluent-tests:
@pip install -r requirements/requirements_build.txt
@poetry install --with test -E reader
@poetry run python -m pytest --write-fluent-journals
@poetry run python .ci/fluent_test_runner.py tests
9 changes: 5 additions & 4 deletions codegen/allapigen.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,9 @@
from time import time

from ansys.fluent.core import CODEGEN_OUTDIR, FluentMode, FluentVersion, launch_fluent
from ansys.fluent.core.codegen import StaticInfoType, allapigen, print_fluent_version
from ansys.fluent.core.search import _search
from ansys.fluent.core.codegen import StaticInfoType, allapigen
from ansys.fluent.core.codegen.print_fluent_version import print_fluent_version
from ansys.fluent.core.search import _generate_api_data
from ansys.fluent.core.utils.fluent_version import get_version_for_file_name

if __name__ == "__main__":
Expand Down Expand Up @@ -60,10 +61,10 @@
t1 = time()
print(f"Time to fetch static info: {t1 - t0:.2f} seconds")
CODEGEN_OUTDIR.mkdir(parents=True, exist_ok=True)
print_fluent_version.generate(version, solver.scheme_eval.scheme_eval)
print_fluent_version(solver._app_utilities)
solver.exit()

allapigen.generate(version, static_infos)
t2 = time()
print(f"Time to generate APIs: {t2 - t1:.2f} seconds")
_search("", version=version, write_api_tree_data=True)
_generate_api_data(version=version)
8 changes: 4 additions & 4 deletions doc/api_rstgen.py
Original file line number Diff line number Diff line change
Expand Up @@ -173,8 +173,8 @@ def _generate_api_source_rst_files(folder: str, files: list):
f".. automodule:: ansys.fluent.core.{folder}.{file}\n"
)
else:
rst.write(f"ansys.fluent.core.{file}\n")
rst.write(f'{"="*(len(f"ansys.fluent.core.{file}"))}\n\n')
rst.write(f"{file}\n")
rst.write(f'{"="*(len(f"{file}"))}\n\n')
rst.write(f".. automodule:: ansys.fluent.core.{file}\n")
if "root" not in file:
_write_common_rst_members(rst_file=rst)
Expand All @@ -191,8 +191,8 @@ def _generate_api_index_rst_files():
file = _get_file_path(folder, "index")
with open(file, "w", encoding="utf8") as index:
index.write(f".. _ref_{folder}:\n\n")
index.write(f"ansys.fluent.core.{folder}\n")
index.write(f'{"="*(len(f"ansys.fluent.core.{folder}"))}\n\n')
index.write(f"{folder}\n")
index.write(f'{"="*(len(f"{folder}"))}\n\n')
index.write(f".. automodule:: ansys.fluent.core.{folder}\n")
_write_common_rst_members(rst_file=index)
index.write(".. toctree::\n")
Expand Down
1 change: 1 addition & 0 deletions doc/source/api/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ full guidelines on their use.
.. toctree::
:maxdepth: 2
:hidden:
:caption: ansys.fluent.core

filereader/index
launcher/index
Expand Down
Loading

0 comments on commit 3e3fa0c

Please sign in to comment.