From 17b8b0c92e9e1e0d0a93c0254cea60f3a7436cfb Mon Sep 17 00:00:00 2001 From: Valentin Seitz Date: Sun, 13 Aug 2023 23:45:53 +0200 Subject: [PATCH 01/19] Added first working prototype --- .../component-templates/openfoam-adapter.yaml | 3 +- tools/tests/dockerfiles/Dockerfile | 102 ++++++++++++++++++ tools/tests/systemtests/Systemtest.py | 5 +- 3 files changed, 107 insertions(+), 3 deletions(-) create mode 100644 tools/tests/dockerfiles/Dockerfile diff --git a/tools/tests/component-templates/openfoam-adapter.yaml b/tools/tests/component-templates/openfoam-adapter.yaml index 44847ba27..4657b6e23 100644 --- a/tools/tests/component-templates/openfoam-adapter.yaml +++ b/tools/tests/component-templates/openfoam-adapter.yaml @@ -1,9 +1,10 @@ build: - context: https://github.com/precice/openfoam-adapter.git#add-ci-docker:tools/docker + context: {{ dockerfile_context }} args: {% for key, value in build_arguments.items() %} - {{key}}={{value}} {% endfor %} + target: openfoam_adapter depends_on: prepare: condition: service_completed_successfully diff --git a/tools/tests/dockerfiles/Dockerfile b/tools/tests/dockerfiles/Dockerfile new file mode 100644 index 000000000..800cb7485 --- /dev/null +++ b/tools/tests/dockerfiles/Dockerfile @@ -0,0 +1,102 @@ +FROM ubuntu:22.04 as base_image +USER root +SHELL ["/bin/bash", "-c"] +ENV DEBIAN_FRONTEND=noninteractive +ENV PATH="${PATH}:/home/precice/.local/bin:/opt/precice/installation/bin" +ENV LD_LIBRARY_PATH="/opt/precice/installation/lib:${LD_LIBRARY_PATH}" +ENV CPATH="/opt/precice/installation/include:$CPATH" +# Enable detection with pkg-config and CMake +ENV PKG_CONFIG_PATH="/opt/precice/installation/pkgconfig:$PKG_CONFIG_PATH" +ENV CMAKE_PREFIX_PATH="/opt/precice/installation:$CMAKE_PREFIX_PATH" + +RUN useradd -ms /bin/bash precice && \ + mkdir -p /opt/precice/installation && \ + chown -R precice:precice /opt/precice/ + +FROM base_image as precice_dependecies +USER root +# Installing necessary dependecies for preCICE +RUN apt-get -qq update && \ + apt-get -qq -y install \ + build-essential \ + software-properties-common \ + ccache \ + cmake \ + curl \ + g++ \ + gfortran \ + git \ + lcov \ + libbenchmark-dev \ + libboost-all-dev \ + libeigen3-dev \ + libxml2-dev \ + lintian \ + lsb-release \ + petsc-dev \ + python3-dev \ + python3-numpy \ + python3-pip \ + python3-venv \ + pkg-config \ + wget +USER precice +RUN python3 -m pip install --user --upgrade pip + + +FROM precice_dependecies as precice +# Install & build precice into /opt/precice/installation +ARG PRECICE_REF=main +USER precice +WORKDIR /opt/precice +RUN git clone https://github.com/precice/precice.git -b ${PRECICE_REF} precice && \ + cd precice && \ + mkdir build && cd build &&\ + cmake .. -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=/opt/precice/installation -DPRECICE_PETScMapping=OFF -DBUILD_TESTING=OFF && \ + make all install -j $(nproc) + +FROM precice_dependecies as openfoam_adapter +COPY --from=precice /opt/precice/installation /opt/precice/installation +ENV PATH="${PATH}:/home/precice/.local/bin:/opt/precice/installation/bin" +ENV LD_LIBRARY_PATH="/opt/precice/installation/lib:${LD_LIBRARY_PATH}" +ENV CPATH="/opt/precice/installation/include:$CPATH" +# Enable detection with pkg-config and CMake +ENV PKG_CONFIG_PATH="/opt/precice/installation/lib/pkgconfig:$PKG_CONFIG_PATH" +ENV CMAKE_PREFIX_PATH="/opt/precice/installation:$CMAKE_PREFIX_PATH" +ARG OPENFOAM_EXECUTABLE=openfoam2112 +USER root +RUN apt-get update &&\ + wget -q -O - https://dl.openfoam.com/add-debian-repo.sh | bash &&\ + apt-get -qq install ${OPENFOAM_EXECUTABLE}-dev &&\ + ln -s $(which ${OPENFOAM_EXECUTABLE} ) /usr/bin/openfoam +ARG OPENFOAM_ADAPTER_REF=master +# Build the OpenFOAM adapter +USER precice +WORKDIR /opt/precice +RUN ls /opt/precice/installation +RUN git clone --depth 1 --branch ${OPENFOAM_ADAPTER_REF} https://github.com/precice/openfoam-adapter.git &&\ + cd openfoam-adapter && /usr/bin/${OPENFOAM_EXECUTABLE} ./Allwmake -j $(nproc) + + +# Will probably not work +FROM precice_dependecies as python_bindings +COPY --from=precice /opt/precice/precice /opt/precice/precice +USER precice +ARG PYTHON_BINDINGS_REF=master +WORKDIR /opt/precice +# Builds the precice python bindings for python3 +RUN pip3 install --target=/opt/precice/python_bindings --prefix=/opt/precice git+https://github.com/precice/python-bindings.git@${PYTHON_BINDINGS_REF} + + +# Will probably not work +FROM precice_dependecies as fenics_adapter +COPY --from=precice /opt/precice/precice /opt/precice/precice +COPY --from=python_bindings /opt/precice/python_bindings /opt/precice/python_bindings +USER root +RUN add-apt-repository -y ppa:fenics-packages/fenics && \ + apt-get -qq update && \ + apt-get -qq install --no-install-recommends fenics +USER precice +ARG FENICS_ADAPTER_REF=master +# Building fenics-adapter +RUN pip3 install --target=/opt/precice/fenics_adapter --prefix=/opt/precice git+https://github.com/precice/fenics-adapter.git@$FENICS_ADAPTER_REF diff --git a/tools/tests/systemtests/Systemtest.py b/tools/tests/systemtests/Systemtest.py index 6cc6be7b5..b002b3475 100644 --- a/tools/tests/systemtests/Systemtest.py +++ b/tools/tests/systemtests/Systemtest.py @@ -5,7 +5,7 @@ from dataclasses import dataclass, field import shutil from pathlib import Path -from paths import PRECICE_REL_OUTPUT_DIR, PRECICE_TOOLS_DIR, PRECICE_REL_REFERENCE_DIR +from paths import PRECICE_REL_OUTPUT_DIR, PRECICE_TOOLS_DIR, PRECICE_REL_REFERENCE_DIR,PRECICE_TESTS_DIR from metadata_parser.metdata import Tutorial, CaseCombination, Case, ReferenceResult from .SystemtestArguments import SystemtestArguments @@ -135,7 +135,8 @@ def render_service_template_per_case(case: Case, params_to_use: Dict[str, str]) 'build_arguments': params_to_use, 'params': params_to_use, 'case_folder': case.path, - 'run': case.run_cmd + 'run': case.run_cmd, + 'dockerfile_context': PRECICE_TESTS_DIR / "dockerfiles" } jinja_env = Environment(loader=FileSystemLoader(system_test_dir)) template = jinja_env.get_template(case.component.template) From 2c5c103647dba234ccb697f3280d2f52d77929c6 Mon Sep 17 00:00:00 2001 From: Valentin Seitz Date: Mon, 14 Aug 2023 13:11:38 +0200 Subject: [PATCH 02/19] added working fenics adapter --- .../component-templates/fenics-adapter.yaml | 11 +++++---- tools/tests/dockerfiles/Dockerfile | 24 +++++++++++++++---- 2 files changed, 26 insertions(+), 9 deletions(-) diff --git a/tools/tests/component-templates/fenics-adapter.yaml b/tools/tests/component-templates/fenics-adapter.yaml index 7b0d41388..b83a23707 100644 --- a/tools/tests/component-templates/fenics-adapter.yaml +++ b/tools/tests/component-templates/fenics-adapter.yaml @@ -1,11 +1,14 @@ -image: precice/fenics-adapter:{{ build_arguments["FENICS_ADAPTER_TAG"] }} -user: ${UID}:${GID} +build: + context: {{ dockerfile_context }} + args: + {% for key, value in build_arguments.items() %} + - {{key}}={{value}} + {% endfor %} + target: fenics_adapter depends_on: prepare: condition: service_completed_successfully volumes: - - /etc/passwd:/etc/passwd:ro - - /etc/group:/etc/group:ro - {{ run_directory }}:/runs command: > /bin/bash -c "id && diff --git a/tools/tests/dockerfiles/Dockerfile b/tools/tests/dockerfiles/Dockerfile index 800cb7485..08ed6926b 100644 --- a/tools/tests/dockerfiles/Dockerfile +++ b/tools/tests/dockerfiles/Dockerfile @@ -80,18 +80,32 @@ RUN git clone --depth 1 --branch ${OPENFOAM_ADAPTER_REF} https://github.com/prec # Will probably not work FROM precice_dependecies as python_bindings -COPY --from=precice /opt/precice/precice /opt/precice/precice +COPY --from=precice /opt/precice/installation /opt/precice/installation +ENV PATH="${PATH}:/home/precice/.local/bin:/opt/precice/installation/bin" +ENV LD_LIBRARY_PATH="/opt/precice/installation/lib:${LD_LIBRARY_PATH}" +ENV CPATH="/opt/precice/installation/include:$CPATH" +# Enable detection with pkg-config and CMake +ENV PKG_CONFIG_PATH="/opt/precice/installation/lib/pkgconfig:$PKG_CONFIG_PATH" +ENV CMAKE_PREFIX_PATH="/opt/precice/installation:$CMAKE_PREFIX_PATH" +ENV PYTHONPATH="/opt/precice/installation/python_bindings:$PYTHONPATH" USER precice ARG PYTHON_BINDINGS_REF=master WORKDIR /opt/precice # Builds the precice python bindings for python3 -RUN pip3 install --target=/opt/precice/python_bindings --prefix=/opt/precice git+https://github.com/precice/python-bindings.git@${PYTHON_BINDINGS_REF} +RUN pip3 install --target=/opt/precice/installation/python_bindings git+https://github.com/precice/python-bindings.git@${PYTHON_BINDINGS_REF} # Will probably not work FROM precice_dependecies as fenics_adapter -COPY --from=precice /opt/precice/precice /opt/precice/precice -COPY --from=python_bindings /opt/precice/python_bindings /opt/precice/python_bindings +COPY --from=precice /opt/precice/installation /opt/precice/installation +COPY --from=python_bindings /opt/precice/installation/python_bindings /opt/precice/installation/python_bindings +ENV PATH="${PATH}:/home/precice/.local/bin:/opt/precice/installation/bin" +ENV LD_LIBRARY_PATH="/opt/precice/installation/lib:${LD_LIBRARY_PATH}" +ENV CPATH="/opt/precice/installation/include:$CPATH" +# Enable detection with pkg-config and CMake +ENV PKG_CONFIG_PATH="/opt/precice/installation/lib/pkgconfig:$PKG_CONFIG_PATH" +ENV CMAKE_PREFIX_PATH="/opt/precice/installation:$CMAKE_PREFIX_PATH" +ENV PYTHONPATH="/opt/precice/installation/python_bindings:/opt/precice/installation/fencis_adapter:$PYTHONPATH" USER root RUN add-apt-repository -y ppa:fenics-packages/fenics && \ apt-get -qq update && \ @@ -99,4 +113,4 @@ RUN add-apt-repository -y ppa:fenics-packages/fenics && \ USER precice ARG FENICS_ADAPTER_REF=master # Building fenics-adapter -RUN pip3 install --target=/opt/precice/fenics_adapter --prefix=/opt/precice git+https://github.com/precice/fenics-adapter.git@$FENICS_ADAPTER_REF +RUN pip3 install --target=/opt/precice/installation/fencis_adapter git+https://github.com/precice/fenics-adapter.git@$FENICS_ADAPTER_REF From 7fbbbe3cfa2cfdb750095812417bb1bb6d11090f Mon Sep 17 00:00:00 2001 From: Valentin Seitz Date: Mon, 14 Aug 2023 13:13:11 +0200 Subject: [PATCH 03/19] remove comments --- tools/tests/dockerfiles/Dockerfile | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tools/tests/dockerfiles/Dockerfile b/tools/tests/dockerfiles/Dockerfile index 08ed6926b..9d176bd52 100644 --- a/tools/tests/dockerfiles/Dockerfile +++ b/tools/tests/dockerfiles/Dockerfile @@ -78,7 +78,7 @@ RUN git clone --depth 1 --branch ${OPENFOAM_ADAPTER_REF} https://github.com/prec cd openfoam-adapter && /usr/bin/${OPENFOAM_EXECUTABLE} ./Allwmake -j $(nproc) -# Will probably not work + FROM precice_dependecies as python_bindings COPY --from=precice /opt/precice/installation /opt/precice/installation ENV PATH="${PATH}:/home/precice/.local/bin:/opt/precice/installation/bin" @@ -95,7 +95,6 @@ WORKDIR /opt/precice RUN pip3 install --target=/opt/precice/installation/python_bindings git+https://github.com/precice/python-bindings.git@${PYTHON_BINDINGS_REF} -# Will probably not work FROM precice_dependecies as fenics_adapter COPY --from=precice /opt/precice/installation /opt/precice/installation COPY --from=python_bindings /opt/precice/installation/python_bindings /opt/precice/installation/python_bindings From a6747f69c39ba27194f5799ad11da2b7724786f7 Mon Sep 17 00:00:00 2001 From: Valentin Seitz Date: Mon, 14 Aug 2023 13:23:45 +0200 Subject: [PATCH 04/19] added working nutils "adapter" --- .../tests/component-templates/nutils-adapter.yaml | 11 +++++++---- tools/tests/dockerfiles/Dockerfile | 15 +++++++++++++++ 2 files changed, 22 insertions(+), 4 deletions(-) diff --git a/tools/tests/component-templates/nutils-adapter.yaml b/tools/tests/component-templates/nutils-adapter.yaml index ae37d38f6..9963028ab 100644 --- a/tools/tests/component-templates/nutils-adapter.yaml +++ b/tools/tests/component-templates/nutils-adapter.yaml @@ -1,11 +1,14 @@ -image: "ghcr.io/precice/openfoam-adapter:{{ build_arguments["openfoam-adapter-ref"] }}" # TODO: Update -user: ${UID}:${GID} +build: + context: {{ dockerfile_context }} + args: + {% for key, value in build_arguments.items() %} + - {{key}}={{value}} + {% endfor %} + target: nutils_adapter depends_on: prepare: condition: service_completed_successfully volumes: - - /etc/passwd:/etc/passwd:ro - - /etc/group:/etc/group:ro - {{ run_directory }}:/runs command: > /bin/bash -c "id && diff --git a/tools/tests/dockerfiles/Dockerfile b/tools/tests/dockerfiles/Dockerfile index 9d176bd52..4380a5a3f 100644 --- a/tools/tests/dockerfiles/Dockerfile +++ b/tools/tests/dockerfiles/Dockerfile @@ -113,3 +113,18 @@ USER precice ARG FENICS_ADAPTER_REF=master # Building fenics-adapter RUN pip3 install --target=/opt/precice/installation/fencis_adapter git+https://github.com/precice/fenics-adapter.git@$FENICS_ADAPTER_REF + + +FROM precice_dependecies as nutils_adapter +COPY --from=precice /opt/precice/installation /opt/precice/installation +COPY --from=python_bindings /opt/precice/installation/python_bindings /opt/precice/installation/python_bindings +ENV PATH="${PATH}:/home/precice/.local/bin:/opt/precice/installation/bin" +ENV LD_LIBRARY_PATH="/opt/precice/installation/lib:${LD_LIBRARY_PATH}" +ENV CPATH="/opt/precice/installation/include:$CPATH" +# Enable detection with pkg-config and CMake +ENV PKG_CONFIG_PATH="/opt/precice/installation/lib/pkgconfig:$PKG_CONFIG_PATH" +ENV CMAKE_PREFIX_PATH="/opt/precice/installation:$CMAKE_PREFIX_PATH" +ENV PYTHONPATH="/opt/precice/installation/python_bindings:/opt/precice/installation/nutils_adapter:$PYTHONPATH" +USER precice +# Building fenics-adapter +RUN pip3 install --target=/opt/precice/installation/nutils_adapter nutils \ No newline at end of file From 48e61ed04dd53a734f73ecb32abe997b3f5b5c0a Mon Sep 17 00:00:00 2001 From: Valentin Seitz Date: Mon, 14 Aug 2023 14:12:17 +0200 Subject: [PATCH 05/19] added not working calclulix -adapter --- .../component-templates/calculix-adapter.yaml | 16 ++++++++++ tools/tests/dockerfiles/Dockerfile | 29 ++++++++++++++++++- 2 files changed, 44 insertions(+), 1 deletion(-) create mode 100644 tools/tests/component-templates/calculix-adapter.yaml diff --git a/tools/tests/component-templates/calculix-adapter.yaml b/tools/tests/component-templates/calculix-adapter.yaml new file mode 100644 index 000000000..038a088b7 --- /dev/null +++ b/tools/tests/component-templates/calculix-adapter.yaml @@ -0,0 +1,16 @@ +build: + context: {{ dockerfile_context }} + args: + {% for key, value in build_arguments.items() %} + - {{key}}={{value}} + {% endfor %} + target: calculix_adapter +depends_on: + prepare: + condition: service_completed_successfully +volumes: + - {{ run_directory }}:/runs +command: > + /bin/bash -c "id && + cd '/runs/{{ tutorial_folder }}/{{ case_folder }}' && + {{ run }} | tee {{ case_folder }}.log 2>&1" diff --git a/tools/tests/dockerfiles/Dockerfile b/tools/tests/dockerfiles/Dockerfile index 4380a5a3f..16dfed5ac 100644 --- a/tools/tests/dockerfiles/Dockerfile +++ b/tools/tests/dockerfiles/Dockerfile @@ -127,4 +127,31 @@ ENV CMAKE_PREFIX_PATH="/opt/precice/installation:$CMAKE_PREFIX_PATH" ENV PYTHONPATH="/opt/precice/installation/python_bindings:/opt/precice/installation/nutils_adapter:$PYTHONPATH" USER precice # Building fenics-adapter -RUN pip3 install --target=/opt/precice/installation/nutils_adapter nutils \ No newline at end of file +RUN pip3 install --target=/opt/precice/installation/nutils_adapter nutils + + +FROM precice_dependecies as calculix_adapter +COPY --from=precice /opt/precice/installation /opt/precice/installation +ENV PATH="${PATH}:/home/precice/.local/bin:/opt/precice/installation/bin" +ENV LD_LIBRARY_PATH="/opt/precice/installation/lib:${LD_LIBRARY_PATH}" +ENV CPATH="/opt/precice/installation/include:$CPATH" +# Enable detection with pkg-config and CMake +ENV PKG_CONFIG_PATH="/opt/precice/installation/lib/pkgconfig:$PKG_CONFIG_PATH" +ENV CMAKE_PREFIX_PATH="/opt/precice/installation:$CMAKE_PREFIX_PATH" +USER root +RUN apt-get -qq update && \ + apt-get -qq install libarpack2-dev libspooles-dev libyaml-cpp-dev +USER precice +ARG CALULIX_VERSION="2.20" +# Building fenics-adapter +WORKDIR /opt/precice/calculix_source +RUN wget http://www.dhondt.de/ccx_${CALULIX_VERSION}.src.tar.bz2 && \ + tar xvjf ccx_${CALULIX_VERSION}.src.tar.bz2 && \ + ln -s $PWD/CalculiX/ccx_${CALULIX_VERSION} /opt/precice/calculix_source/current + +ARG CALULIX_ADAPTER_REF=v2.20.0 +WORKDIR /opt/precice +RUN git clone --depth 1 --branch ${CALULIX_ADAPTER_REF} https://github.com/precice/calculix-adapter.git && \ + cd calculix-adapter && \ + make CCX="/opt/precice/calculix_source/current/src" CCX_VERSION="${CALULIX_VERSION}" && \ + ln -s /opt/precice/calculix_source/current/src/ccx_preCICE /opt/precice/installation/bin/ccx_preCICE From 2d61f8fe6b31e47880fc682cdf689fc4fb0fa220 Mon Sep 17 00:00:00 2001 From: Valentin Seitz Date: Mon, 14 Aug 2023 17:21:55 +0200 Subject: [PATCH 06/19] reorder dockerfile --- tools/tests/dockerfiles/Dockerfile | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/tools/tests/dockerfiles/Dockerfile b/tools/tests/dockerfiles/Dockerfile index 16dfed5ac..7cb7042f1 100644 --- a/tools/tests/dockerfiles/Dockerfile +++ b/tools/tests/dockerfiles/Dockerfile @@ -56,6 +56,13 @@ RUN git clone https://github.com/precice/precice.git -b ${PRECICE_REF} precice & make all install -j $(nproc) FROM precice_dependecies as openfoam_adapter +ARG OPENFOAM_EXECUTABLE=openfoam2112 +USER root +RUN apt-get update &&\ + wget -q -O - https://dl.openfoam.com/add-debian-repo.sh | bash &&\ + apt-get -qq install ${OPENFOAM_EXECUTABLE}-dev &&\ + ln -s $(which ${OPENFOAM_EXECUTABLE} ) /usr/bin/openfoam + COPY --from=precice /opt/precice/installation /opt/precice/installation ENV PATH="${PATH}:/home/precice/.local/bin:/opt/precice/installation/bin" ENV LD_LIBRARY_PATH="/opt/precice/installation/lib:${LD_LIBRARY_PATH}" @@ -63,12 +70,7 @@ ENV CPATH="/opt/precice/installation/include:$CPATH" # Enable detection with pkg-config and CMake ENV PKG_CONFIG_PATH="/opt/precice/installation/lib/pkgconfig:$PKG_CONFIG_PATH" ENV CMAKE_PREFIX_PATH="/opt/precice/installation:$CMAKE_PREFIX_PATH" -ARG OPENFOAM_EXECUTABLE=openfoam2112 -USER root -RUN apt-get update &&\ - wget -q -O - https://dl.openfoam.com/add-debian-repo.sh | bash &&\ - apt-get -qq install ${OPENFOAM_EXECUTABLE}-dev &&\ - ln -s $(which ${OPENFOAM_EXECUTABLE} ) /usr/bin/openfoam + ARG OPENFOAM_ADAPTER_REF=master # Build the OpenFOAM adapter USER precice From a57a3ee29776e778de599e61f22d544559388a83 Mon Sep 17 00:00:00 2001 From: Valentin Seitz Date: Mon, 14 Aug 2023 17:29:06 +0200 Subject: [PATCH 07/19] make autopep8 happy --- tools/tests/systemtests/Systemtest.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/tests/systemtests/Systemtest.py b/tools/tests/systemtests/Systemtest.py index b002b3475..7939d5874 100644 --- a/tools/tests/systemtests/Systemtest.py +++ b/tools/tests/systemtests/Systemtest.py @@ -5,7 +5,7 @@ from dataclasses import dataclass, field import shutil from pathlib import Path -from paths import PRECICE_REL_OUTPUT_DIR, PRECICE_TOOLS_DIR, PRECICE_REL_REFERENCE_DIR,PRECICE_TESTS_DIR +from paths import PRECICE_REL_OUTPUT_DIR, PRECICE_TOOLS_DIR, PRECICE_REL_REFERENCE_DIR, PRECICE_TESTS_DIR from metadata_parser.metdata import Tutorial, CaseCombination, Case, ReferenceResult from .SystemtestArguments import SystemtestArguments From 8bf4b33e38ed41dbc4159a1257042a24e894be30 Mon Sep 17 00:00:00 2001 From: Valentin Seitz Date: Mon, 14 Aug 2023 17:31:24 +0200 Subject: [PATCH 08/19] fix print_case_combinations --- tools/tests/print_case_combinations.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/tests/print_case_combinations.py b/tools/tests/print_case_combinations.py index 9176331d5..a3778c4cd 100644 --- a/tools/tests/print_case_combinations.py +++ b/tools/tests/print_case_combinations.py @@ -11,6 +11,6 @@ for tutorial in available_tutorials: cases_combinations = [ f"{combination}" for combination in tutorial.case_combinations] - tutorials[tutorial.path] = cases_combinations + tutorials[tutorial.path.name] = cases_combinations print(yaml.dump(tutorials)) From 3f560eea069d730e7224c2fc1ad4d10e2c872ab0 Mon Sep 17 00:00:00 2001 From: Valentin Seitz Date: Tue, 15 Aug 2023 20:56:18 +0200 Subject: [PATCH 09/19] WIP --- tools/tests/components.yaml | 44 ++++++++++++++------ tools/tests/docker-compose.template.yaml | 7 ++-- tools/tests/dockerfiles/Dockerfile | 18 ++++----- tools/tests/generate_reference_data.py | 15 +++++-- tools/tests/reference_versions.yaml | 9 +++-- tools/tests/systemtests/Systemtest.py | 51 ++++++++++++++++++++---- tools/tests/tests.yaml | 22 ++++++++++ 7 files changed, 127 insertions(+), 39 deletions(-) diff --git a/tools/tests/components.yaml b/tools/tests/components.yaml index f7aac37dc..fe096b4a4 100644 --- a/tools/tests/components.yaml +++ b/tools/tests/components.yaml @@ -2,11 +2,14 @@ openfoam-adapter: repository: https://github.com/precice/openfoam-adapter template: component-templates/openfoam-adapter.yaml build_arguments: # these things mean something to the docker-service + TUTORIALS_REF: + description: Tutorial git reference to use + default: "" OPENFOAM_EXECUTABLE: - options: ["openfoam2112"] + options: ["openfoam2306","openfoam2212",openfoam2112] description: exectuable of openfoam to use - default: "openfoam2112" - PRECICE_TAG: + default: "openfoam2306" + PRECICE_REF: description: Version of preCICE to use default: "latest" OPENFOAM_ADAPTER_REF: @@ -17,23 +20,38 @@ fenics-adapter: repository: https://github.com/precice/fenics-adapter template: component-templates/fenics-adapter.yaml build_arguments: - FENICS_ADAPTER_TAG: - semnantic: Version of the fenics adapter image to use + TUTORIALS_REF: + description: Tutorial git reference to use + default: "" + PRECICE_REF: + description: Version of preCICE to use default: "latest" + PYTHON_BINDINGS_REF: + semnantic: Git ref of the pythonbindings to use + default: "master" + FENICS_ADAPTER_REF: + semnantic: Git ref of the fenics adapter to use + default: "master" -calculix-adapter: - repository: https://github.com/precice/calculix-adapter - template: component-templates/calculix-adapter.yaml +nutils-adapter: + repository: https://github.com/precice/nutils-adapter + template: component-templates/nutils-adapter.yaml build_arguments: - PRECICE_TAG: + TUTORIALS_REF: + description: Tutorial git reference to use + default: "" + PRECICE_REF: description: Version of preCICE to use default: "latest" + PYTHON_BINDINGS_REF: + semnantic: Git ref of the pythonbindings to use + default: "master" - -nutils-adapter: - repository: https://github.com/precice/nutils-adapter - template: component-templates/nutils-adapter.yaml +# NOT WORKING +calculix-adapter: + repository: https://github.com/precice/calculix-adapter + template: component-templates/calculix-adapter.yaml build_arguments: PRECICE_TAG: description: Version of preCICE to use diff --git a/tools/tests/docker-compose.template.yaml b/tools/tests/docker-compose.template.yaml index a259eea24..ff6f7d279 100644 --- a/tools/tests/docker-compose.template.yaml +++ b/tools/tests/docker-compose.template.yaml @@ -1,11 +1,12 @@ version: "3.9" services: prepare: - image: ubuntu:latest - user: ${UID}:${GID} + build: + context: {{ dockerfile_context }} + target: base_image volumes: - {{ run_directory }}:/runs - # tar -zxf reference-output.tar.gz && + command: > /bin/bash -c "id && cd '/runs/{{ tutorial_folder }}' && diff --git a/tools/tests/dockerfiles/Dockerfile b/tools/tests/dockerfiles/Dockerfile index 7cb7042f1..414de173d 100644 --- a/tools/tests/dockerfiles/Dockerfile +++ b/tools/tests/dockerfiles/Dockerfile @@ -12,6 +12,7 @@ ENV CMAKE_PREFIX_PATH="/opt/precice/installation:$CMAKE_PREFIX_PATH" RUN useradd -ms /bin/bash precice && \ mkdir -p /opt/precice/installation && \ chown -R precice:precice /opt/precice/ +USER precice FROM base_image as precice_dependecies USER root @@ -20,18 +21,15 @@ RUN apt-get -qq update && \ apt-get -qq -y install \ build-essential \ software-properties-common \ - ccache \ cmake \ curl \ g++ \ gfortran \ git \ - lcov \ libbenchmark-dev \ libboost-all-dev \ libeigen3-dev \ libxml2-dev \ - lintian \ lsb-release \ petsc-dev \ python3-dev \ @@ -46,17 +44,17 @@ RUN python3 -m pip install --user --upgrade pip FROM precice_dependecies as precice # Install & build precice into /opt/precice/installation -ARG PRECICE_REF=main +ARG PRECICE_REF USER precice WORKDIR /opt/precice -RUN git clone https://github.com/precice/precice.git -b ${PRECICE_REF} precice && \ +RUN git clone --depth 1 https://github.com/precice/precice.git -b ${PRECICE_REF} precice && \ cd precice && \ mkdir build && cd build &&\ cmake .. -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=/opt/precice/installation -DPRECICE_PETScMapping=OFF -DBUILD_TESTING=OFF && \ make all install -j $(nproc) FROM precice_dependecies as openfoam_adapter -ARG OPENFOAM_EXECUTABLE=openfoam2112 +ARG OPENFOAM_EXECUTABLE USER root RUN apt-get update &&\ wget -q -O - https://dl.openfoam.com/add-debian-repo.sh | bash &&\ @@ -71,7 +69,7 @@ ENV CPATH="/opt/precice/installation/include:$CPATH" ENV PKG_CONFIG_PATH="/opt/precice/installation/lib/pkgconfig:$PKG_CONFIG_PATH" ENV CMAKE_PREFIX_PATH="/opt/precice/installation:$CMAKE_PREFIX_PATH" -ARG OPENFOAM_ADAPTER_REF=master +ARG OPENFOAM_ADAPTER_REF # Build the OpenFOAM adapter USER precice WORKDIR /opt/precice @@ -91,7 +89,7 @@ ENV PKG_CONFIG_PATH="/opt/precice/installation/lib/pkgconfig:$PKG_CONFIG_PATH" ENV CMAKE_PREFIX_PATH="/opt/precice/installation:$CMAKE_PREFIX_PATH" ENV PYTHONPATH="/opt/precice/installation/python_bindings:$PYTHONPATH" USER precice -ARG PYTHON_BINDINGS_REF=master +ARG PYTHON_BINDINGS_REF WORKDIR /opt/precice # Builds the precice python bindings for python3 RUN pip3 install --target=/opt/precice/installation/python_bindings git+https://github.com/precice/python-bindings.git@${PYTHON_BINDINGS_REF} @@ -112,7 +110,7 @@ RUN add-apt-repository -y ppa:fenics-packages/fenics && \ apt-get -qq update && \ apt-get -qq install --no-install-recommends fenics USER precice -ARG FENICS_ADAPTER_REF=master +ARG FENICS_ADAPTER_REF # Building fenics-adapter RUN pip3 install --target=/opt/precice/installation/fencis_adapter git+https://github.com/precice/fenics-adapter.git@$FENICS_ADAPTER_REF @@ -132,6 +130,8 @@ USER precice RUN pip3 install --target=/opt/precice/installation/nutils_adapter nutils + +## STILL WIP FROM precice_dependecies as calculix_adapter COPY --from=precice /opt/precice/installation /opt/precice/installation ENV PATH="${PATH}:/home/precice/.local/bin:/opt/precice/installation/bin" diff --git a/tools/tests/generate_reference_data.py b/tools/tests/generate_reference_data.py index b6272d7b6..8c7504def 100644 --- a/tools/tests/generate_reference_data.py +++ b/tools/tests/generate_reference_data.py @@ -17,7 +17,6 @@ def create_tar_gz(source_folder: Path, output_filename: Path): with tarfile.open(output_filename, "w:gz") as tar: - print(source_folder, output_filename) tar.add(source_folder, arcname=output_filename.name.replace(".tar.gz", "")) @@ -84,14 +83,24 @@ def calculate_sha1(file_path: Path): print(f"About to run the following tests {systemtests_to_run}") for systemtest in systemtests_to_run: - systemtest.run_for_reference_results(run_directory) + result = systemtest.run_for_reference_results(run_directory) + if not result.success: + print(f"Failed to execute {systemtest}") + exit(1) reference_result_per_tutorial[systemtest.tutorial] = [] # Put the tar.gz in there for systemtest in systemtests_to_run: reference_result_folder = systemtest.get_system_test_dir() / PRECICE_REL_OUTPUT_DIR reference_result_per_tutorial[systemtest.tutorial].append(systemtest.reference_result) - create_tar_gz(reference_result_folder, systemtest.reference_result.path) + # create folder if needed + systemtest.reference_result.path.parent.mkdir(parents=True, exist_ok=True) + if reference_result_folder.exists(): + create_tar_gz(reference_result_folder, systemtest.reference_result.path) + else: + print(f"{systemtest}:") + print(f"\t Could not find {reference_result_folder}") + exit(1) # write readme for tutorial in reference_result_per_tutorial.keys(): diff --git a/tools/tests/reference_versions.yaml b/tools/tests/reference_versions.yaml index 61c095293..d7242c47e 100644 --- a/tools/tests/reference_versions.yaml +++ b/tools/tests/reference_versions.yaml @@ -1,3 +1,6 @@ -OPENFOAM_EXECUTABLE: "openfoam2112" -PRECICE_TAG: "latest" -OPENFOAM_ADAPTER_REF: "master" +PRECICE_REF: "v2.5.0" +OPENFOAM_EXECUTABLE: "openfoam2206" +OPENFOAM_ADAPTER_REF: "master" #"v1.2.0" +PYTHON_BINDINGS_REF: "master" #"v2.5.0.1" +FENICS_ADAPTER_REF: "master" #"v1.4.0" +TUTORIALS_REF: "master" \ No newline at end of file diff --git a/tools/tests/systemtests/Systemtest.py b/tools/tests/systemtests/Systemtest.py index 7939d5874..0ea2e433e 100644 --- a/tools/tests/systemtests/Systemtest.py +++ b/tools/tests/systemtests/Systemtest.py @@ -1,11 +1,11 @@ import os import subprocess -from typing import List, Dict, Tuple +from typing import List, Dict, Optional from jinja2 import Environment, FileSystemLoader from dataclasses import dataclass, field import shutil from pathlib import Path -from paths import PRECICE_REL_OUTPUT_DIR, PRECICE_TOOLS_DIR, PRECICE_REL_REFERENCE_DIR, PRECICE_TESTS_DIR +from paths import PRECICE_REL_OUTPUT_DIR, PRECICE_TOOLS_DIR, PRECICE_REL_REFERENCE_DIR, PRECICE_TESTS_DIR, PRECICE_TUTORIAL_DIR from metadata_parser.metdata import Tutorial, CaseCombination, Case, ReferenceResult from .SystemtestArguments import SystemtestArguments @@ -173,12 +173,47 @@ def __get_field_compare_compose_file(self): "docker-compose.field_compare.template.yaml") return template.render(render_dict) + def _get_git_ref(self, repository: Path) -> Optional[str]: + try: + result = subprocess.run([ + "git", + "-C", repository.resolve(), + "rev-parse", + "HEAD"], stdout=subprocess.PIPE, + stderr=subprocess.PIPE, text=True, check=True) + current_ref = result.stdout.strip() + return current_ref + except subprocess.CalledProcessError as e: + print(f"An error occurred while getting the current Git ref: {e}") + return None + + def _checkout_ref_in_subfolder(self, repository: Path, subfolder: Path, ref: str): + try: + result = subprocess.run([ + "git", + "-C", repository.resolve(), + "checkout", ref, + "--", subfolder.resolve() + ], check=True) + if result.returncode != 0: + print(f"FAILD checking out '{ref}' for folder '{subfolder}'.") + exit(1) + + except subprocess.CalledProcessError as e: + print(f"An error occurred while checking out '{ref}' for folder '{repository}': {e}") + def __copy_tutorial_into_directory(self, run_directory: Path): """ - Copies the entire tutorial into a folder to prepare for running. + Checks out the requested tutorial ref and copies the entire tutorial into a folder to prepare for running. """ current_time_string = datetime.now().strftime('%Y-%m-%d %H:%M:%S') self.run_directory = run_directory + current_ref = self._get_git_ref(PRECICE_TUTORIAL_DIR) + ref_requested = self.arguments.get("TUTORIALS_REF") + if ref_requested: + print(f"Checking out tutorials {ref_requested} before copying") + self._checkout_ref_in_subfolder(PRECICE_TUTORIAL_DIR,self.tutorial.path,ref_requested) + self.tutorial_folder = slugify(f'{self.tutorial.path.name}_{self.case_combination.cases}_{current_time_string}') destination = run_directory / self.tutorial_folder src = self.tutorial.path @@ -341,14 +376,14 @@ def run(self, run_directory: Path): docker_compose_result = self._run_tutorial() std_out.extend(docker_compose_result.stdout_data) std_err.extend(docker_compose_result.stderr_data) - if docker_compose_result.exit_code == 1: + if docker_compose_result.exit_code != 0: self.__handle_docker_compose_failure(docker_compose_result) return SystemtestResult(False, std_out, std_err, self) fieldcompare_result = self._run_field_compare() std_out.extend(fieldcompare_result.stdout_data) std_err.extend(fieldcompare_result.stderr_data) - if fieldcompare_result.exit_code == 1: + if fieldcompare_result.exit_code != 1: self.__handle_field_compare_failure(fieldcompare_result) return SystemtestResult(False, std_out, std_err, self) @@ -371,11 +406,11 @@ def run_for_reference_results(self, run_directory: Path): docker_compose_result = self._run_tutorial() std_out.extend(docker_compose_result.stdout_data) std_err.extend(docker_compose_result.stderr_data) - if docker_compose_result.exit_code == 1: + if docker_compose_result.exit_code == 0: + return SystemtestResult(True, std_out, std_err, self) + else: self.__handle_docker_compose_failure(docker_compose_result) return SystemtestResult(False, std_out, std_err, self) - return SystemtestResult(True, std_out, std_err, self) - def get_system_test_dir(self) -> Path: return self.system_test_dir diff --git a/tools/tests/tests.yaml b/tools/tests/tests.yaml index 58d92c6b9..a8cc69187 100644 --- a/tools/tests/tests.yaml +++ b/tools/tests/tests.yaml @@ -13,3 +13,25 @@ test_suites: - fluid-openfoam - solid-openfoam reference_result: ./flow-over-heated-plate/reference-data/fluid-openfoam_solid-openfoam.tar.gz +# fenics_test: +# tutorials: +# - path: flow-over-heated-plate +# case_combination: +# +# - fluid-openfoam +# - solid-fenics +# reference_result: ./flow-over-heated-plate/reference-data/fluid-openfoam_solid-fenics.tar.gz +# nutils_test: +# tutorials: +# - path: flow-over-heated-plate +# case_combination: +# - fluid-openfoam +# - solid-nutils +# reference_result: ./flow-over-heated-plate/reference-data/fluid-openfoam_solid-nutils.tar.gz +# nutils_fenics_test: +# tutorials: +# - path: perpendicular-flap +# case_combination: +# - fluid-nutils +# - solid-fenics +# reference_result: ./perpendicular-flap/reference-data/fluid-nutils_solid-nutils.tar.gz \ No newline at end of file From a8b7b9ff46d0f77e7f13468491d1d098b31af14f Mon Sep 17 00:00:00 2001 From: Valentin Seitz Date: Fri, 18 Aug 2023 18:38:23 +0200 Subject: [PATCH 10/19] WIP --- tools/tests/dockerfiles/Dockerfile | 2 ++ tools/tests/generate_reference_data.py | 3 +- tools/tests/reference_versions.yaml | 17 +++++++--- tools/tests/systemtests/Systemtest.py | 10 +++++- tools/tests/tests.yaml | 45 +++++++++++++------------- 5 files changed, 48 insertions(+), 29 deletions(-) diff --git a/tools/tests/dockerfiles/Dockerfile b/tools/tests/dockerfiles/Dockerfile index 414de173d..26a065538 100644 --- a/tools/tests/dockerfiles/Dockerfile +++ b/tools/tests/dockerfiles/Dockerfile @@ -112,6 +112,8 @@ RUN add-apt-repository -y ppa:fenics-packages/fenics && \ USER precice ARG FENICS_ADAPTER_REF # Building fenics-adapter +RUN pip3 install fenics-ufl +# COmment out requirement.txt RUN pip3 install --target=/opt/precice/installation/fencis_adapter git+https://github.com/precice/fenics-adapter.git@$FENICS_ADAPTER_REF diff --git a/tools/tests/generate_reference_data.py b/tools/tests/generate_reference_data.py index 8c7504def..f232bcd9f 100644 --- a/tools/tests/generate_reference_data.py +++ b/tools/tests/generate_reference_data.py @@ -99,7 +99,7 @@ def calculate_sha1(file_path: Path): create_tar_gz(reference_result_folder, systemtest.reference_result.path) else: print(f"{systemtest}:") - print(f"\t Could not find {reference_result_folder}") + print(f"\t Could not find {reference_result_folder}\n Probably the tutorial did not run through properly. Please check the logs") exit(1) # write readme @@ -107,4 +107,5 @@ def calculate_sha1(file_path: Path): with open(tutorial.path / "reference_results.md", 'w') as file: ref_results_info = render_reference_results_info( reference_result_per_tutorial[tutorial], build_args, current_time_string) + print(f"writing results for {tutorial.name}" ) file.write(ref_results_info) diff --git a/tools/tests/reference_versions.yaml b/tools/tests/reference_versions.yaml index d7242c47e..a022c17ff 100644 --- a/tools/tests/reference_versions.yaml +++ b/tools/tests/reference_versions.yaml @@ -1,6 +1,13 @@ -PRECICE_REF: "v2.5.0" +PRECICE_REF: "main" OPENFOAM_EXECUTABLE: "openfoam2206" -OPENFOAM_ADAPTER_REF: "master" #"v1.2.0" -PYTHON_BINDINGS_REF: "master" #"v2.5.0.1" -FENICS_ADAPTER_REF: "master" #"v1.4.0" -TUTORIALS_REF: "master" \ No newline at end of file +OPENFOAM_ADAPTER_REF: "master" +PYTHON_BINDINGS_REF: "master" +FENICS_ADAPTER_REF: "master" +TUTORIALS_REF: "master" + +#PRECICE_REF: "v2.5.0" +#OPENFOAM_EXECUTABLE: "openfoam2206" +#OPENFOAM_ADAPTER_REF: "v1.2.0" +#PYTHON_BINDINGS_REF: "v2.5.0.1" +#FENICS_ADAPTER_REF: "v1.4.0" +#TUTORIALS_REF: "v202211.0" \ No newline at end of file diff --git a/tools/tests/systemtests/Systemtest.py b/tools/tests/systemtests/Systemtest.py index 0ea2e433e..f5b0bd628 100644 --- a/tools/tests/systemtests/Systemtest.py +++ b/tools/tests/systemtests/Systemtest.py @@ -155,6 +155,7 @@ def __get_docker_compose_file(self): 'tutorial_folder': self.tutorial_folder, 'tutorial': self.tutorial.path.name, 'services': rendered_services, + 'dockerfile_context': PRECICE_TESTS_DIR / "dockerfiles", 'precice_output_folder': PRECICE_REL_OUTPUT_DIR, } jinja_env = Environment(loader=FileSystemLoader(system_test_dir)) @@ -173,12 +174,13 @@ def __get_field_compare_compose_file(self): "docker-compose.field_compare.template.yaml") return template.render(render_dict) - def _get_git_ref(self, repository: Path) -> Optional[str]: + def _get_git_ref(self, repository: Path, abbrev_ref=False) -> Optional[str]: try: result = subprocess.run([ "git", "-C", repository.resolve(), "rev-parse", + "--abbrev-ref" if abbrev_ref else "HEAD"], stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True, check=True) current_ref = result.stdout.strip() @@ -220,6 +222,12 @@ def __copy_tutorial_into_directory(self, run_directory: Path): self.system_test_dir = destination shutil.copytree(src, destination) + with open(destination / "tutorials_ref", 'w') as file: + file.write(ref_requested) + + if ref_requested: + self._checkout_ref_in_subfolder(PRECICE_TUTORIAL_DIR,self.tutorial.path,current_ref) + def __copy_tools(self, run_directory: Path): destination = run_directory / "tools" src = PRECICE_TOOLS_DIR diff --git a/tools/tests/tests.yaml b/tools/tests/tests.yaml index a8cc69187..2efe53188 100644 --- a/tools/tests/tests.yaml +++ b/tools/tests/tests.yaml @@ -13,25 +13,26 @@ test_suites: - fluid-openfoam - solid-openfoam reference_result: ./flow-over-heated-plate/reference-data/fluid-openfoam_solid-openfoam.tar.gz -# fenics_test: -# tutorials: -# - path: flow-over-heated-plate -# case_combination: -# -# - fluid-openfoam -# - solid-fenics -# reference_result: ./flow-over-heated-plate/reference-data/fluid-openfoam_solid-fenics.tar.gz -# nutils_test: -# tutorials: -# - path: flow-over-heated-plate -# case_combination: -# - fluid-openfoam -# - solid-nutils -# reference_result: ./flow-over-heated-plate/reference-data/fluid-openfoam_solid-nutils.tar.gz -# nutils_fenics_test: -# tutorials: -# - path: perpendicular-flap -# case_combination: -# - fluid-nutils -# - solid-fenics -# reference_result: ./perpendicular-flap/reference-data/fluid-nutils_solid-nutils.tar.gz \ No newline at end of file + fenics_test: + tutorials: + - path: flow-over-heated-plate + case_combination: + + - fluid-openfoam + - solid-fenics + reference_result: ./flow-over-heated-plate/reference-data/fluid-openfoam_solid-fenics.tar.gz + reference_time: + nutils_test: + tutorials: + - path: flow-over-heated-plate + case_combination: + - fluid-openfoam + - solid-nutils + reference_result: ./flow-over-heated-plate/reference-data/fluid-openfoam_solid-nutils.tar.gz + nutils_fenics_test: + tutorials: + - path: perpendicular-flap + case_combination: + - fluid-nutils + - solid-fenics + reference_result: ./perpendicular-flap/reference-data/fluid-nutils_solid-nutils.tar.gz \ No newline at end of file From 14bba11c56f9796ec984f287e485f7cecf975650 Mon Sep 17 00:00:00 2001 From: Valentin Seitz Date: Sun, 20 Aug 2023 13:30:36 +0200 Subject: [PATCH 11/19] - Introduced logging instead of prints - refactored into exceptions instead of exit(1) - --- tools/tests/dockerfiles/Dockerfile | 161 ------------------ .../tests/dockerfiles/ubuntu_2204/Dockerfile | 140 +++++++++++++++ tools/tests/generate_reference_data.py | 14 +- tools/tests/reference_versions.yaml | 2 +- tools/tests/systemtests.py | 16 +- tools/tests/systemtests/Systemtest.py | 52 +++--- .../tests/systemtests/SystemtestArguments.py | 3 +- 7 files changed, 187 insertions(+), 201 deletions(-) delete mode 100644 tools/tests/dockerfiles/Dockerfile create mode 100644 tools/tests/dockerfiles/ubuntu_2204/Dockerfile diff --git a/tools/tests/dockerfiles/Dockerfile b/tools/tests/dockerfiles/Dockerfile deleted file mode 100644 index 26a065538..000000000 --- a/tools/tests/dockerfiles/Dockerfile +++ /dev/null @@ -1,161 +0,0 @@ -FROM ubuntu:22.04 as base_image -USER root -SHELL ["/bin/bash", "-c"] -ENV DEBIAN_FRONTEND=noninteractive -ENV PATH="${PATH}:/home/precice/.local/bin:/opt/precice/installation/bin" -ENV LD_LIBRARY_PATH="/opt/precice/installation/lib:${LD_LIBRARY_PATH}" -ENV CPATH="/opt/precice/installation/include:$CPATH" -# Enable detection with pkg-config and CMake -ENV PKG_CONFIG_PATH="/opt/precice/installation/pkgconfig:$PKG_CONFIG_PATH" -ENV CMAKE_PREFIX_PATH="/opt/precice/installation:$CMAKE_PREFIX_PATH" - -RUN useradd -ms /bin/bash precice && \ - mkdir -p /opt/precice/installation && \ - chown -R precice:precice /opt/precice/ -USER precice - -FROM base_image as precice_dependecies -USER root -# Installing necessary dependecies for preCICE -RUN apt-get -qq update && \ - apt-get -qq -y install \ - build-essential \ - software-properties-common \ - cmake \ - curl \ - g++ \ - gfortran \ - git \ - libbenchmark-dev \ - libboost-all-dev \ - libeigen3-dev \ - libxml2-dev \ - lsb-release \ - petsc-dev \ - python3-dev \ - python3-numpy \ - python3-pip \ - python3-venv \ - pkg-config \ - wget -USER precice -RUN python3 -m pip install --user --upgrade pip - - -FROM precice_dependecies as precice -# Install & build precice into /opt/precice/installation -ARG PRECICE_REF -USER precice -WORKDIR /opt/precice -RUN git clone --depth 1 https://github.com/precice/precice.git -b ${PRECICE_REF} precice && \ - cd precice && \ - mkdir build && cd build &&\ - cmake .. -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=/opt/precice/installation -DPRECICE_PETScMapping=OFF -DBUILD_TESTING=OFF && \ - make all install -j $(nproc) - -FROM precice_dependecies as openfoam_adapter -ARG OPENFOAM_EXECUTABLE -USER root -RUN apt-get update &&\ - wget -q -O - https://dl.openfoam.com/add-debian-repo.sh | bash &&\ - apt-get -qq install ${OPENFOAM_EXECUTABLE}-dev &&\ - ln -s $(which ${OPENFOAM_EXECUTABLE} ) /usr/bin/openfoam - -COPY --from=precice /opt/precice/installation /opt/precice/installation -ENV PATH="${PATH}:/home/precice/.local/bin:/opt/precice/installation/bin" -ENV LD_LIBRARY_PATH="/opt/precice/installation/lib:${LD_LIBRARY_PATH}" -ENV CPATH="/opt/precice/installation/include:$CPATH" -# Enable detection with pkg-config and CMake -ENV PKG_CONFIG_PATH="/opt/precice/installation/lib/pkgconfig:$PKG_CONFIG_PATH" -ENV CMAKE_PREFIX_PATH="/opt/precice/installation:$CMAKE_PREFIX_PATH" - -ARG OPENFOAM_ADAPTER_REF -# Build the OpenFOAM adapter -USER precice -WORKDIR /opt/precice -RUN ls /opt/precice/installation -RUN git clone --depth 1 --branch ${OPENFOAM_ADAPTER_REF} https://github.com/precice/openfoam-adapter.git &&\ - cd openfoam-adapter && /usr/bin/${OPENFOAM_EXECUTABLE} ./Allwmake -j $(nproc) - - - -FROM precice_dependecies as python_bindings -COPY --from=precice /opt/precice/installation /opt/precice/installation -ENV PATH="${PATH}:/home/precice/.local/bin:/opt/precice/installation/bin" -ENV LD_LIBRARY_PATH="/opt/precice/installation/lib:${LD_LIBRARY_PATH}" -ENV CPATH="/opt/precice/installation/include:$CPATH" -# Enable detection with pkg-config and CMake -ENV PKG_CONFIG_PATH="/opt/precice/installation/lib/pkgconfig:$PKG_CONFIG_PATH" -ENV CMAKE_PREFIX_PATH="/opt/precice/installation:$CMAKE_PREFIX_PATH" -ENV PYTHONPATH="/opt/precice/installation/python_bindings:$PYTHONPATH" -USER precice -ARG PYTHON_BINDINGS_REF -WORKDIR /opt/precice -# Builds the precice python bindings for python3 -RUN pip3 install --target=/opt/precice/installation/python_bindings git+https://github.com/precice/python-bindings.git@${PYTHON_BINDINGS_REF} - - -FROM precice_dependecies as fenics_adapter -COPY --from=precice /opt/precice/installation /opt/precice/installation -COPY --from=python_bindings /opt/precice/installation/python_bindings /opt/precice/installation/python_bindings -ENV PATH="${PATH}:/home/precice/.local/bin:/opt/precice/installation/bin" -ENV LD_LIBRARY_PATH="/opt/precice/installation/lib:${LD_LIBRARY_PATH}" -ENV CPATH="/opt/precice/installation/include:$CPATH" -# Enable detection with pkg-config and CMake -ENV PKG_CONFIG_PATH="/opt/precice/installation/lib/pkgconfig:$PKG_CONFIG_PATH" -ENV CMAKE_PREFIX_PATH="/opt/precice/installation:$CMAKE_PREFIX_PATH" -ENV PYTHONPATH="/opt/precice/installation/python_bindings:/opt/precice/installation/fencis_adapter:$PYTHONPATH" -USER root -RUN add-apt-repository -y ppa:fenics-packages/fenics && \ - apt-get -qq update && \ - apt-get -qq install --no-install-recommends fenics -USER precice -ARG FENICS_ADAPTER_REF -# Building fenics-adapter -RUN pip3 install fenics-ufl -# COmment out requirement.txt -RUN pip3 install --target=/opt/precice/installation/fencis_adapter git+https://github.com/precice/fenics-adapter.git@$FENICS_ADAPTER_REF - - -FROM precice_dependecies as nutils_adapter -COPY --from=precice /opt/precice/installation /opt/precice/installation -COPY --from=python_bindings /opt/precice/installation/python_bindings /opt/precice/installation/python_bindings -ENV PATH="${PATH}:/home/precice/.local/bin:/opt/precice/installation/bin" -ENV LD_LIBRARY_PATH="/opt/precice/installation/lib:${LD_LIBRARY_PATH}" -ENV CPATH="/opt/precice/installation/include:$CPATH" -# Enable detection with pkg-config and CMake -ENV PKG_CONFIG_PATH="/opt/precice/installation/lib/pkgconfig:$PKG_CONFIG_PATH" -ENV CMAKE_PREFIX_PATH="/opt/precice/installation:$CMAKE_PREFIX_PATH" -ENV PYTHONPATH="/opt/precice/installation/python_bindings:/opt/precice/installation/nutils_adapter:$PYTHONPATH" -USER precice -# Building fenics-adapter -RUN pip3 install --target=/opt/precice/installation/nutils_adapter nutils - - - -## STILL WIP -FROM precice_dependecies as calculix_adapter -COPY --from=precice /opt/precice/installation /opt/precice/installation -ENV PATH="${PATH}:/home/precice/.local/bin:/opt/precice/installation/bin" -ENV LD_LIBRARY_PATH="/opt/precice/installation/lib:${LD_LIBRARY_PATH}" -ENV CPATH="/opt/precice/installation/include:$CPATH" -# Enable detection with pkg-config and CMake -ENV PKG_CONFIG_PATH="/opt/precice/installation/lib/pkgconfig:$PKG_CONFIG_PATH" -ENV CMAKE_PREFIX_PATH="/opt/precice/installation:$CMAKE_PREFIX_PATH" -USER root -RUN apt-get -qq update && \ - apt-get -qq install libarpack2-dev libspooles-dev libyaml-cpp-dev -USER precice -ARG CALULIX_VERSION="2.20" -# Building fenics-adapter -WORKDIR /opt/precice/calculix_source -RUN wget http://www.dhondt.de/ccx_${CALULIX_VERSION}.src.tar.bz2 && \ - tar xvjf ccx_${CALULIX_VERSION}.src.tar.bz2 && \ - ln -s $PWD/CalculiX/ccx_${CALULIX_VERSION} /opt/precice/calculix_source/current - -ARG CALULIX_ADAPTER_REF=v2.20.0 -WORKDIR /opt/precice -RUN git clone --depth 1 --branch ${CALULIX_ADAPTER_REF} https://github.com/precice/calculix-adapter.git && \ - cd calculix-adapter && \ - make CCX="/opt/precice/calculix_source/current/src" CCX_VERSION="${CALULIX_VERSION}" && \ - ln -s /opt/precice/calculix_source/current/src/ccx_preCICE /opt/precice/installation/bin/ccx_preCICE diff --git a/tools/tests/dockerfiles/ubuntu_2204/Dockerfile b/tools/tests/dockerfiles/ubuntu_2204/Dockerfile new file mode 100644 index 000000000..e360d0047 --- /dev/null +++ b/tools/tests/dockerfiles/ubuntu_2204/Dockerfile @@ -0,0 +1,140 @@ +FROM ubuntu:22.04 as base_image +USER root +SHELL ["/bin/bash", "-c"] +ENV DEBIAN_FRONTEND=noninteractive +ENV PATH="${PATH}:/home/precice/.local/bin:/opt/precice/installation/bin" +ENV LD_LIBRARY_PATH="/opt/precice/installation/lib:${LD_LIBRARY_PATH}" +ENV CPATH="/opt/precice/installation/include:$CPATH" +# Enable detection with pkg-config and CMake +ENV PKG_CONFIG_PATH="/opt/precice/installation/pkgconfig:$PKG_CONFIG_PATH" +ENV CMAKE_PREFIX_PATH="/opt/precice/installation:$CMAKE_PREFIX_PATH" + +RUN useradd -ms /bin/bash precice +USER precice + +FROM base_image as precice_dependecies +USER root +# Installing necessary dependecies for preCICE +RUN apt-get -qq update && \ + apt-get -qq -y install \ + build-essential \ + software-properties-common \ + cmake \ + curl \ + g++ \ + gfortran \ + git \ + libbenchmark-dev \ + libboost-all-dev \ + libeigen3-dev \ + libxml2-dev \ + lsb-release \ + petsc-dev \ + python3-dev \ + python3-numpy \ + python3-pip \ + python3-venv \ + pkg-config \ + wget +USER precice +RUN python3 -m pip install --user --upgrade pip + + +FROM precice_dependecies as precice +# Install & build precice into /home/precice/precice +ARG PRECICE_REF +USER precice +WORKDIR /home/precice +RUN git clone --depth 1 https://github.com/precice/precice.git -b ${PRECICE_REF} precice && \ + cd precice && \ + mkdir build && cd build &&\ + cmake .. -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=/home/precice/.local/ -DPRECICE_PETScMapping=OFF -DBUILD_TESTING=OFF && \ + make all install -j $(nproc) + +FROM precice_dependecies as openfoam_adapter +ARG OPENFOAM_EXECUTABLE +USER root +RUN apt-get update &&\ + wget -q -O - https://dl.openfoam.com/add-debian-repo.sh | bash &&\ + apt-get -qq install ${OPENFOAM_EXECUTABLE}-dev &&\ + ln -s $(which ${OPENFOAM_EXECUTABLE} ) /usr/bin/openfoam + +USER precice +COPY --from=precice /home/precice/.local/ /home/precice/.local/ +ENV PATH="${PATH}:/home/precice/.local/bin" +ENV LD_LIBRARY_PATH="/home/precice/.local/lib:${LD_LIBRARY_PATH}" +ENV CPATH="/home/precice/.local/include:$CPATH" +# Enable detection with pkg-config and CMake +ENV PKG_CONFIG_PATH="/home/precice/.local/lib/pkgconfig:$PKG_CONFIG_PATH" +ENV CMAKE_PREFIX_PATH="/home/precice/.local:$CMAKE_PREFIX_PATH" + +ARG OPENFOAM_ADAPTER_REF +# Build the OpenFOAM adapter +USER precice +WORKDIR /home/precice +RUN git clone --depth 1 --branch ${OPENFOAM_ADAPTER_REF} https://github.com/precice/openfoam-adapter.git &&\ + cd openfoam-adapter && /usr/bin/${OPENFOAM_EXECUTABLE} ./Allwmake -j $(nproc) + + + +FROM precice_dependecies as python_bindings +COPY --from=precice /home/precice/.local /home/precice/.local +ENV PATH="${PATH}:/home/precice/.local/bin" +ENV LD_LIBRARY_PATH="/home/precice/.local/lib:${LD_LIBRARY_PATH}" +ENV CPATH="/home/precice/.local/include:$CPATH" +# Enable detection with pkg-config and CMake +ENV PKG_CONFIG_PATH="/home/precice/.local/lib/pkgconfig:$PKG_CONFIG_PATH" +ENV CMAKE_PREFIX_PATH="/home/precice/.local:$CMAKE_PREFIX_PATH" +USER precice +ARG PYTHON_BINDINGS_REF +WORKDIR /home/precice +# Builds the precice python bindings for python3 +RUN pip3 install --user git+https://github.com/precice/python-bindings.git@${PYTHON_BINDINGS_REF} + + +FROM precice_dependecies as fenics_adapter +COPY --from=python_bindings /home/precice/.local /home/precice/.local +USER root +RUN add-apt-repository -y ppa:fenics-packages/fenics && \ + apt-get -qq update && \ + apt-get -qq install --no-install-recommends fenics +USER precice +RUN pip3 install fenics-ufl +ARG FENICS_ADAPTER_REF +# Building fenics-adapter +RUN pip3 install --user git+https://github.com/precice/fenics-adapter.git@${FENICS_ADAPTER_REF} + + +FROM precice_dependecies as nutils_adapter +COPY --from=python_bindings /home/precice/.local /home/precice/.local +USER precice +# Building fenics-adapter +RUN pip3 install --user nutils + + + +## STILL WIP +FROM precice_dependecies as calculix_adapter +COPY --from=precice /home/precice/.local /home/precice/.local +ENV PATH="${PATH}:/home/precice/.local/bin" +ENV LD_LIBRARY_PATH="/home/precice/.local/lib:${LD_LIBRARY_PATH}" +ENV CPATH="/home/precice/.local/include:$CPATH" +# Enable detection with pkg-config and CMake +ENV PKG_CONFIG_PATH="/home/precice/.local/lib/pkgconfig:$PKG_CONFIG_PATH" +ENV CMAKE_PREFIX_PATH="/home/precice/.local:$CMAKE_PREFIX_PATH" +USER root +RUN apt-get -qq update && \ + apt-get -qq install libarpack2-dev libspooles-dev libyaml-cpp-dev +USER precice +ARG CALULIX_VERSION="2.20" +# Building fenics-adapter +WORKDIR /home/precice +RUN wget http://www.dhondt.de/ccx_${CALULIX_VERSION}.src.tar.bz2 && \ + tar xvjf ccx_${CALULIX_VERSION}.src.tar.bz2 && + +ARG CALULIX_ADAPTER_REF=v2.20.0 +WORKDIR /opt/precice +RUN git clone --depth 1 --branch ${CALULIX_ADAPTER_REF} https://github.com/precice/calculix-adapter.git && \ + cd calculix-adapter && \ + make CCX="/home/precice//CalculiX/ccx_${CALULIX_VERSION}/src" CCX_VERSION="${CALULIX_VERSION}" && \ + ln -s /opt/precice/calculix_source/current/src/ccx_preCICE /home/precice/.local/bin/ccx_preCICE diff --git a/tools/tests/generate_reference_data.py b/tools/tests/generate_reference_data.py index f232bcd9f..c0452d78e 100644 --- a/tools/tests/generate_reference_data.py +++ b/tools/tests/generate_reference_data.py @@ -11,7 +11,7 @@ from jinja2 import Environment, FileSystemLoader import tarfile from datetime import datetime - +import logging from paths import PRECICE_TUTORIAL_DIR, PRECICE_TESTS_RUN_DIR, PRECICE_TESTS_DIR, PRECICE_REL_OUTPUT_DIR @@ -81,12 +81,11 @@ def calculate_sha1(file_path: Path): current_time_string = datetime.now().strftime('%Y-%m-%d %H:%M:%S') -print(f"About to run the following tests {systemtests_to_run}") +logging.info(f"About to run the following tests {systemtests_to_run}") for systemtest in systemtests_to_run: result = systemtest.run_for_reference_results(run_directory) if not result.success: - print(f"Failed to execute {systemtest}") - exit(1) + raise RuntimeError("Failed to execute {systemtest}") reference_result_per_tutorial[systemtest.tutorial] = [] # Put the tar.gz in there @@ -98,14 +97,13 @@ def calculate_sha1(file_path: Path): if reference_result_folder.exists(): create_tar_gz(reference_result_folder, systemtest.reference_result.path) else: - print(f"{systemtest}:") - print(f"\t Could not find {reference_result_folder}\n Probably the tutorial did not run through properly. Please check the logs") - exit(1) + raise RuntimeError( + f"Error executing: \n {systemtest} \n Could not find result folder {reference_result_folder}\n Probably the tutorial did not run through properly. Please check corresponding logs") # write readme for tutorial in reference_result_per_tutorial.keys(): with open(tutorial.path / "reference_results.md", 'w') as file: ref_results_info = render_reference_results_info( reference_result_per_tutorial[tutorial], build_args, current_time_string) - print(f"writing results for {tutorial.name}" ) + logging.info(f"writing results for {tutorial.name}") file.write(ref_results_info) diff --git a/tools/tests/reference_versions.yaml b/tools/tests/reference_versions.yaml index a022c17ff..846557d37 100644 --- a/tools/tests/reference_versions.yaml +++ b/tools/tests/reference_versions.yaml @@ -4,7 +4,7 @@ OPENFOAM_ADAPTER_REF: "master" PYTHON_BINDINGS_REF: "master" FENICS_ADAPTER_REF: "master" TUTORIALS_REF: "master" - +PLATFORM: "ubuntu_2204" #PRECICE_REF: "v2.5.0" #OPENFOAM_EXECUTABLE: "openfoam2206" #OPENFOAM_ADAPTER_REF: "v1.2.0" diff --git a/tools/tests/systemtests.py b/tools/tests/systemtests.py index f3707f886..69de229f8 100644 --- a/tools/tests/systemtests.py +++ b/tools/tests/systemtests.py @@ -5,7 +5,7 @@ from systemtests.Systemtest import Systemtest from systemtests.TestSuite import TestSuites from metadata_parser.metdata import Tutorials, Case - +import logging from paths import PRECICE_TUTORIAL_DIR, PRECICE_TESTS_RUN_DIR, PRECICE_TESTS_DIR @@ -38,12 +38,11 @@ test_suite_found = available_testsuites.get_by_name( test_suite_requested) if not test_suite_found: - print( - f"Warning: did not find the testsuite with name {test_suite_requested}") + logging.error(f"Did not find the testsuite with name {test_suite_requested}") else: test_suites_to_execute.append(test_suite_found) if not test_suites_to_execute: - raise Exception( + raise RuntimeError( f"No matching test suites with names {test_suites_requested} found. Use print_test_suites.py to get an overview") # now convert the test_suites into systemtests for test_suite in test_suites_to_execute: @@ -56,11 +55,10 @@ if not systemtests_to_run: - raise Exception("Did not find any Systemtests to execute.") + raise RuntimeError("Did not find any Systemtests to execute.") -print( - f"About to run the following systemtest in the directory {run_directory}: \n{systemtests_to_run}") +logging.info(f"About to run the following systemtest in the directory {run_directory}: \n{systemtests_to_run}") results = [] for systemtest in systemtests_to_run: @@ -69,10 +67,10 @@ system_test_success = True for result in results: if not result.success: - print(f"Failed to run {result.systemtest}") + logging.error(f"Failed to run {result.systemtest}") system_test_success = False else: - print(f"Success running {result.systemtest}") + logging.info(f"Success running {result.systemtest}") if system_test_success: exit(0) diff --git a/tools/tests/systemtests/Systemtest.py b/tools/tests/systemtests/Systemtest.py index f5b0bd628..b73a07983 100644 --- a/tools/tests/systemtests/Systemtest.py +++ b/tools/tests/systemtests/Systemtest.py @@ -15,6 +15,7 @@ import unicodedata import re +import logging def slugify(value, allow_unicode=False): @@ -128,6 +129,16 @@ def __get_docker_services(self) -> Dict[str, str]: Returns: A dictionary of rendered services per case name. """ + try: + plaform_requested = self.arguments.get("PLATFORM") + except Exception as exc: + raise KeyError("Please specify a PLATFORM argument") from exc + + self.dockerfile_context = PRECICE_TESTS_DIR / "dockerfiles" / Path(plaform_requested) + if not self.dockerfile_context.exists(): + raise ValueError( + f"The path {self.dockerfile_context.resolve()} resulting from argument PLATFORM={plaform_requested} could not be found in the system") + def render_service_template_per_case(case: Case, params_to_use: Dict[str, str]) -> str: render_dict = { 'run_directory': self.run_directory.resolve(), @@ -136,7 +147,7 @@ def render_service_template_per_case(case: Case, params_to_use: Dict[str, str]) 'params': params_to_use, 'case_folder': case.path, 'run': case.run_cmd, - 'dockerfile_context': PRECICE_TESTS_DIR / "dockerfiles" + 'dockerfile_context': self.dockerfile_context, } jinja_env = Environment(loader=FileSystemLoader(system_test_dir)) template = jinja_env.get_template(case.component.template) @@ -155,7 +166,7 @@ def __get_docker_compose_file(self): 'tutorial_folder': self.tutorial_folder, 'tutorial': self.tutorial.path.name, 'services': rendered_services, - 'dockerfile_context': PRECICE_TESTS_DIR / "dockerfiles", + 'dockerfile_context': self.dockerfile_context, 'precice_output_folder': PRECICE_REL_OUTPUT_DIR, } jinja_env = Environment(loader=FileSystemLoader(system_test_dir)) @@ -186,8 +197,7 @@ def _get_git_ref(self, repository: Path, abbrev_ref=False) -> Optional[str]: current_ref = result.stdout.strip() return current_ref except subprocess.CalledProcessError as e: - print(f"An error occurred while getting the current Git ref: {e}") - return None + raise RuntimeError(f"An error occurred while getting the current Git ref: {e}") from e def _checkout_ref_in_subfolder(self, repository: Path, subfolder: Path, ref: str): try: @@ -198,11 +208,10 @@ def _checkout_ref_in_subfolder(self, repository: Path, subfolder: Path, ref: str "--", subfolder.resolve() ], check=True) if result.returncode != 0: - print(f"FAILD checking out '{ref}' for folder '{subfolder}'.") - exit(1) + raise RuntimeError(f"git command return code {result.returncode}") - except subprocess.CalledProcessError as e: - print(f"An error occurred while checking out '{ref}' for folder '{repository}': {e}") + except Exception as e: + raise RuntimeError(f"An error occurred while checking out '{ref}' for folder '{repository}': {e}") def __copy_tutorial_into_directory(self, run_directory: Path): """ @@ -213,9 +222,9 @@ def __copy_tutorial_into_directory(self, run_directory: Path): current_ref = self._get_git_ref(PRECICE_TUTORIAL_DIR) ref_requested = self.arguments.get("TUTORIALS_REF") if ref_requested: - print(f"Checking out tutorials {ref_requested} before copying") - self._checkout_ref_in_subfolder(PRECICE_TUTORIAL_DIR,self.tutorial.path,ref_requested) - + logging.debug(f"Checking out tutorials {ref_requested} before copying") + self._checkout_ref_in_subfolder(PRECICE_TUTORIAL_DIR, self.tutorial.path, ref_requested) + self.tutorial_folder = slugify(f'{self.tutorial.path.name}_{self.case_combination.cases}_{current_time_string}') destination = run_directory / self.tutorial_folder src = self.tutorial.path @@ -226,7 +235,7 @@ def __copy_tutorial_into_directory(self, run_directory: Path): file.write(ref_requested) if ref_requested: - self._checkout_ref_in_subfolder(PRECICE_TUTORIAL_DIR,self.tutorial.path,current_ref) + self._checkout_ref_in_subfolder(PRECICE_TUTORIAL_DIR, self.tutorial.path, current_ref) def __copy_tools(self, run_directory: Path): destination = run_directory / "tools" @@ -234,7 +243,7 @@ def __copy_tools(self, run_directory: Path): try: shutil.copytree(src, destination) except Exception as e: - print("tools are already copied: ", e) + logging.debug("tools are already copied: ", e) def __put_gitignore(self, run_directory: Path): # Create the .gitignore file with a single asterisk @@ -251,7 +260,7 @@ def __get_uid_gid(self): gid = int(subprocess.check_output(["id", "-g"]).strip()) return uid, gid except Exception as e: - print("Error getting group and user id: ", e) + logging.error("Error getting group and user id: ", e) def __write_env_file(self): with open(self.system_test_dir / ".env", "w") as env_file: @@ -262,7 +271,8 @@ def __unpack_reference_results(self): with tarfile.open(self.reference_result.path) as reference_results_tared: # specify which folder to extract to reference_results_tared.extractall(self.system_test_dir / PRECICE_REL_REFERENCE_DIR) - print(f"extracting {self.reference_result.path} into {self.system_test_dir / PRECICE_REL_REFERENCE_DIR}") + logging.debug( + f"extracting {self.reference_result.path} into {self.system_test_dir / PRECICE_REL_REFERENCE_DIR}") def _run_field_compare(self): """ @@ -301,7 +311,7 @@ def _run_field_compare(self): break if output: stdout_data.append(output) - print(output, end='') + logging.debug(output, end='') # Capture remaining output stdout, stderr = process.communicate() @@ -311,7 +321,7 @@ def _run_field_compare(self): exit_code = process.wait() return FieldCompareResult(exit_code, stdout_data, stderr_data, self) except Exception as e: - print("Error executing docker compose command:", e) + logging.CRITICAL("Error executing docker compose command:", e) return FieldCompareResult(1, stdout_data, stderr_data, self) def _run_tutorial(self): @@ -346,7 +356,7 @@ def _run_tutorial(self): break if output: stdout_data.append(output) - print(output, end='') + logging.debug(output, end='') # Capture remaining output stdout, stderr = process.communicate() @@ -356,17 +366,17 @@ def _run_tutorial(self): exit_code = process.wait() return DockerComposeResult(exit_code, stdout_data, stderr_data, self) except Exception as e: - print("Error executing docker compose command:", e) + logging.critical("Error executing docker compose command:", e) return DockerComposeResult(1, stdout_data, stderr_data, self) def __repr__(self): return f"{self.tutorial.name} {self.case_combination}" def __handle_docker_compose_failure(self, result: DockerComposeResult): - print("Docker Compose failed, skipping fieldcompare") + logging.critical("Docker Compose failed, skipping fieldcompare") def __handle_field_compare_failure(self, result: FieldCompareResult): - print("Fieldcompare failed") + logging.error("Fieldcompare failed") def run(self, run_directory: Path): """ diff --git a/tools/tests/systemtests/SystemtestArguments.py b/tools/tests/systemtests/SystemtestArguments.py index 4afd5e6ba..2b7b3eeec 100644 --- a/tools/tests/systemtests/SystemtestArguments.py +++ b/tools/tests/systemtests/SystemtestArguments.py @@ -1,5 +1,6 @@ from dataclasses import dataclass import yaml +from typing import Optional @dataclass @@ -34,5 +35,5 @@ def __repr__(self): def contains(self, argument_key): return argument_key in self.arguments.keys() - def get(self, argument_key): + def get(self, argument_key) -> Optional[str]: return self.arguments[argument_key] From 3bc7ddcd2b348051296e275c2306f3682e7e185c Mon Sep 17 00:00:00 2001 From: Valentin Seitz Date: Tue, 29 Aug 2023 00:33:19 +0200 Subject: [PATCH 12/19] - Added Nutils - Added Calculix - Added reference results for some cases - Added heat exchanger tutorial - Added logging and more verbose output - Added timing output --- .../fluid-openfoam_solid-fenics.tar.gz | 3 + .../fluid-openfoam_solid-nutils.tar.gz | 3 + .../fluid-openfoam_solid-openfoam.tar.gz | 4 +- flow-over-heated-plate/reference_results.md | 18 ++- heat-exchanger-simplified/metadata.yaml | 29 ++++ .../fluid-openfoam_solid-calculix.tar.gz | 3 + perpendicular-flap/reference_results.md | 27 ++++ tools/tests/components.yaml | 52 +++++-- .../tests/dockerfiles/ubuntu_2204/Dockerfile | 58 +++---- tools/tests/generate_reference_data.py | 143 +++++++++-------- tools/tests/print_case_combinations.py | 38 +++-- tools/tests/print_metadata.py | 27 +++- tools/tests/print_test_suites.py | 32 +++- tools/tests/reference_results.template | 4 +- tools/tests/reference_versions.yaml | 20 +-- tools/tests/systemtests.py | 147 ++++++++++-------- tools/tests/systemtests/Systemtest.py | 103 ++++++------ tools/tests/tests.yaml | 11 +- 18 files changed, 438 insertions(+), 284 deletions(-) create mode 100644 flow-over-heated-plate/reference-data/fluid-openfoam_solid-fenics.tar.gz create mode 100644 flow-over-heated-plate/reference-data/fluid-openfoam_solid-nutils.tar.gz create mode 100644 heat-exchanger-simplified/metadata.yaml create mode 100644 perpendicular-flap/reference-data/fluid-openfoam_solid-calculix.tar.gz create mode 100644 perpendicular-flap/reference_results.md diff --git a/flow-over-heated-plate/reference-data/fluid-openfoam_solid-fenics.tar.gz b/flow-over-heated-plate/reference-data/fluid-openfoam_solid-fenics.tar.gz new file mode 100644 index 000000000..57d94e61f --- /dev/null +++ b/flow-over-heated-plate/reference-data/fluid-openfoam_solid-fenics.tar.gz @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:5eb3653447273dc6d16bd1066db6fd8537d7af32b520ba5e894d4abfad7fd5c8 +size 778129 diff --git a/flow-over-heated-plate/reference-data/fluid-openfoam_solid-nutils.tar.gz b/flow-over-heated-plate/reference-data/fluid-openfoam_solid-nutils.tar.gz new file mode 100644 index 000000000..2465b69fb --- /dev/null +++ b/flow-over-heated-plate/reference-data/fluid-openfoam_solid-nutils.tar.gz @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:cabb7a8283289d7a2222a996432b72bbfad0cc8514562e01d0426b1e5fc05b64 +size 532514 diff --git a/flow-over-heated-plate/reference-data/fluid-openfoam_solid-openfoam.tar.gz b/flow-over-heated-plate/reference-data/fluid-openfoam_solid-openfoam.tar.gz index 61cf44283..36fc19592 100644 --- a/flow-over-heated-plate/reference-data/fluid-openfoam_solid-openfoam.tar.gz +++ b/flow-over-heated-plate/reference-data/fluid-openfoam_solid-openfoam.tar.gz @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7a0976d2fc7a421a75036cd5d888aad1526a8e86fa65912c046d96f6b74171ca -size 498892 +oid sha256:21058f307ccba7531a99c820daf6674b47a7bc1c3a7f40829126d20c41779c43 +size 498330 diff --git a/flow-over-heated-plate/reference_results.md b/flow-over-heated-plate/reference_results.md index 8189c99ae..2c3c848c0 100644 --- a/flow-over-heated-plate/reference_results.md +++ b/flow-over-heated-plate/reference_results.md @@ -8,14 +8,22 @@ This file contains an overview of the results over the reference results as well ## List of files -| name | time | sha-1 | +| name | time | sha256 | |------|------|-------| -| fluid-openfoam_solid-openfoam.tar.gz | 2023-08-13 14:52:04 | bd8b4d235c8326e75deef3f03a1d8277c429972a | +| fluid-openfoam_solid-openfoam.tar.gz | 2023-08-28 23:42:54 | 21058f307ccba7531a99c820daf6674b47a7bc1c3a7f40829126d20c41779c43 | +| fluid-openfoam_solid-nutils.tar.gz | 2023-08-28 23:42:54 | cabb7a8283289d7a2222a996432b72bbfad0cc8514562e01d0426b1e5fc05b64 | +| fluid-openfoam_solid-fenics.tar.gz | 2023-08-28 23:42:54 | 5eb3653447273dc6d16bd1066db6fd8537d7af32b520ba5e894d4abfad7fd5c8 | ## List of arguments used to generate the files | name | value | |------|------| -| OPENFOAM_EXECUTABLE | openfoam2112 | -| PRECICE_TAG | latest | -| OPENFOAM_ADAPTER_REF | master | +| PRECICE_REF | v2.5.0 | +| OPENFOAM_EXECUTABLE | openfoam2306 | +| OPENFOAM_ADAPTER_REF | v1.2.3 | +| PYTHON_BINDINGS_REF | v2.5.0.4 | +| FENICS_ADAPTER_REF | v1.4.0 | +| TUTORIALS_REF | v202211.0 | +| PLATFORM | ubuntu_2204 | +| CALULIX_VERSION | 2.20 | +| CALULIX_ADAPTER_REF | v2.20.0 | diff --git a/heat-exchanger-simplified/metadata.yaml b/heat-exchanger-simplified/metadata.yaml new file mode 100644 index 000000000..124e76f9d --- /dev/null +++ b/heat-exchanger-simplified/metadata.yaml @@ -0,0 +1,29 @@ +name: Heat Exchanger simplified +path: heat-exchanger-simplified # relative to git repo +url: https://precice.org/tutorials-heat-exchanger-simplified.html + +participants: + - Fluid-Top + - Fluid-Bottom + - Solid + +cases: + fluid-btm-openfoam: + participant: Fluid-Bottom + directory: ./fluid-bottom-openfoam + run: ./run.sh + component: openfoam-adapter + + fluid-top-openfoam: + participant: Fluid-Top + directory: ./fluid-top-openfoam + run: ./run.sh + component: openfoam-adapter + + solid-calculix: + participant: Solid + directory: ./solid-calculix + run: ./run.sh + component: calculix-adapter + + diff --git a/perpendicular-flap/reference-data/fluid-openfoam_solid-calculix.tar.gz b/perpendicular-flap/reference-data/fluid-openfoam_solid-calculix.tar.gz new file mode 100644 index 000000000..070c78f5f --- /dev/null +++ b/perpendicular-flap/reference-data/fluid-openfoam_solid-calculix.tar.gz @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:35686e4cb9dd8d1b58efd1d17fd63db4dba75fa9b650b2ec9bceca1a71951c04 +size 13561579 diff --git a/perpendicular-flap/reference_results.md b/perpendicular-flap/reference_results.md new file mode 100644 index 000000000..d683c20cc --- /dev/null +++ b/perpendicular-flap/reference_results.md @@ -0,0 +1,27 @@ + + +# Reference Results + +This file contains an overview of the results over the reference results as well as the arguments used to generate them. + +## List of files + +| name | time | sha256 | +|------|------|-------| +| fluid-openfoam_solid-calculix.tar.gz | 2023-08-28 23:42:54 | 35686e4cb9dd8d1b58efd1d17fd63db4dba75fa9b650b2ec9bceca1a71951c04 | + +## List of arguments used to generate the files + +| name | value | +|------|------| +| PRECICE_REF | v2.5.0 | +| OPENFOAM_EXECUTABLE | openfoam2306 | +| OPENFOAM_ADAPTER_REF | v1.2.3 | +| PYTHON_BINDINGS_REF | v2.5.0.4 | +| FENICS_ADAPTER_REF | v1.4.0 | +| TUTORIALS_REF | v202211.0 | +| PLATFORM | ubuntu_2204 | +| CALULIX_VERSION | 2.20 | +| CALULIX_ADAPTER_REF | v2.20.0 | diff --git a/tools/tests/components.yaml b/tools/tests/components.yaml index fe096b4a4..fb35293b2 100644 --- a/tools/tests/components.yaml +++ b/tools/tests/components.yaml @@ -2,30 +2,37 @@ openfoam-adapter: repository: https://github.com/precice/openfoam-adapter template: component-templates/openfoam-adapter.yaml build_arguments: # these things mean something to the docker-service + PRECICE_REF: + description: Version of preCICE to use + default: "main" + PLATFORM: + description: Dockerfile platform used + default: "ubuntu_2204" TUTORIALS_REF: description: Tutorial git reference to use - default: "" + default: "master" OPENFOAM_EXECUTABLE: options: ["openfoam2306","openfoam2212",openfoam2112] description: exectuable of openfoam to use default: "openfoam2306" - PRECICE_REF: - description: Version of preCICE to use - default: "latest" OPENFOAM_ADAPTER_REF: description: Reference/tag of the actual OpenFOAM adapter default: "master" + fenics-adapter: repository: https://github.com/precice/fenics-adapter template: component-templates/fenics-adapter.yaml build_arguments: - TUTORIALS_REF: - description: Tutorial git reference to use - default: "" PRECICE_REF: description: Version of preCICE to use - default: "latest" + default: "main" + PLATFORM: + description: Dockerfile platform used + default: "ubuntu_2204" + TUTORIALS_REF: + description: Tutorial git reference to use + default: "master" PYTHON_BINDINGS_REF: semnantic: Git ref of the pythonbindings to use default: "master" @@ -37,22 +44,35 @@ nutils-adapter: repository: https://github.com/precice/nutils-adapter template: component-templates/nutils-adapter.yaml build_arguments: - TUTORIALS_REF: - description: Tutorial git reference to use - default: "" PRECICE_REF: description: Version of preCICE to use - default: "latest" + default: "main" + PLATFORM: + description: Dockerfile platform used + default: "ubuntu_2204" + TUTORIALS_REF: + description: Tutorial git reference to use + default: "master" PYTHON_BINDINGS_REF: semnantic: Git ref of the pythonbindings to use - default: "master" -# NOT WORKING calculix-adapter: repository: https://github.com/precice/calculix-adapter template: component-templates/calculix-adapter.yaml build_arguments: - PRECICE_TAG: + PRECICE_REF: description: Version of preCICE to use - default: "latest" + default: "main" + PLATFORM: + description: Dockerfile platform used + default: "ubuntu_2204" + TUTORIALS_REF: + description: Tutorial git reference to use + default: "master" + CALULIX_VERSION: + description: Version of Calculix to use + default: "2.20" + CALULIX_ADAPTER_REF: + description: Version of Calculix-Adapter to use + default: "master" \ No newline at end of file diff --git a/tools/tests/dockerfiles/ubuntu_2204/Dockerfile b/tools/tests/dockerfiles/ubuntu_2204/Dockerfile index e360d0047..f12b7af4d 100644 --- a/tools/tests/dockerfiles/ubuntu_2204/Dockerfile +++ b/tools/tests/dockerfiles/ubuntu_2204/Dockerfile @@ -2,14 +2,14 @@ FROM ubuntu:22.04 as base_image USER root SHELL ["/bin/bash", "-c"] ENV DEBIAN_FRONTEND=noninteractive -ENV PATH="${PATH}:/home/precice/.local/bin:/opt/precice/installation/bin" -ENV LD_LIBRARY_PATH="/opt/precice/installation/lib:${LD_LIBRARY_PATH}" -ENV CPATH="/opt/precice/installation/include:$CPATH" -# Enable detection with pkg-config and CMake -ENV PKG_CONFIG_PATH="/opt/precice/installation/pkgconfig:$PKG_CONFIG_PATH" -ENV CMAKE_PREFIX_PATH="/opt/precice/installation:$CMAKE_PREFIX_PATH" RUN useradd -ms /bin/bash precice +ENV PATH="${PATH}:/home/precice/.local/bin" +ENV LD_LIBRARY_PATH="/home/precice/.local/lib:${LD_LIBRARY_PATH}" +ENV CPATH="/home/precice/.local/include:$CPATH" +# Enable detection with pkg-config and CMake +ENV PKG_CONFIG_PATH="/home/precice/.local/lib/pkgconfig:$PKG_CONFIG_PATH" +ENV CMAKE_PREFIX_PATH="/home/precice/.local:$CMAKE_PREFIX_PATH" USER precice FROM base_image as precice_dependecies @@ -58,35 +58,20 @@ RUN apt-get update &&\ wget -q -O - https://dl.openfoam.com/add-debian-repo.sh | bash &&\ apt-get -qq install ${OPENFOAM_EXECUTABLE}-dev &&\ ln -s $(which ${OPENFOAM_EXECUTABLE} ) /usr/bin/openfoam - USER precice COPY --from=precice /home/precice/.local/ /home/precice/.local/ -ENV PATH="${PATH}:/home/precice/.local/bin" -ENV LD_LIBRARY_PATH="/home/precice/.local/lib:${LD_LIBRARY_PATH}" -ENV CPATH="/home/precice/.local/include:$CPATH" -# Enable detection with pkg-config and CMake -ENV PKG_CONFIG_PATH="/home/precice/.local/lib/pkgconfig:$PKG_CONFIG_PATH" -ENV CMAKE_PREFIX_PATH="/home/precice/.local:$CMAKE_PREFIX_PATH" - ARG OPENFOAM_ADAPTER_REF # Build the OpenFOAM adapter USER precice WORKDIR /home/precice -RUN git clone --depth 1 --branch ${OPENFOAM_ADAPTER_REF} https://github.com/precice/openfoam-adapter.git &&\ +RUN git clone --depth 1 -b ${OPENFOAM_ADAPTER_REF} https://github.com/precice/openfoam-adapter.git &&\ cd openfoam-adapter && /usr/bin/${OPENFOAM_EXECUTABLE} ./Allwmake -j $(nproc) - FROM precice_dependecies as python_bindings -COPY --from=precice /home/precice/.local /home/precice/.local -ENV PATH="${PATH}:/home/precice/.local/bin" -ENV LD_LIBRARY_PATH="/home/precice/.local/lib:${LD_LIBRARY_PATH}" -ENV CPATH="/home/precice/.local/include:$CPATH" -# Enable detection with pkg-config and CMake -ENV PKG_CONFIG_PATH="/home/precice/.local/lib/pkgconfig:$PKG_CONFIG_PATH" -ENV CMAKE_PREFIX_PATH="/home/precice/.local:$CMAKE_PREFIX_PATH" -USER precice +COPY --from=precice /home/precice/.local/ /home/precice/.local/ ARG PYTHON_BINDINGS_REF +USER precice WORKDIR /home/precice # Builds the precice python bindings for python3 RUN pip3 install --user git+https://github.com/precice/python-bindings.git@${PYTHON_BINDINGS_REF} @@ -99,7 +84,7 @@ RUN add-apt-repository -y ppa:fenics-packages/fenics && \ apt-get -qq update && \ apt-get -qq install --no-install-recommends fenics USER precice -RUN pip3 install fenics-ufl +RUN pip3 install --user fenics-ufl ARG FENICS_ADAPTER_REF # Building fenics-adapter RUN pip3 install --user git+https://github.com/precice/fenics-adapter.git@${FENICS_ADAPTER_REF} @@ -112,29 +97,22 @@ USER precice RUN pip3 install --user nutils - -## STILL WIP FROM precice_dependecies as calculix_adapter COPY --from=precice /home/precice/.local /home/precice/.local -ENV PATH="${PATH}:/home/precice/.local/bin" -ENV LD_LIBRARY_PATH="/home/precice/.local/lib:${LD_LIBRARY_PATH}" -ENV CPATH="/home/precice/.local/include:$CPATH" -# Enable detection with pkg-config and CMake -ENV PKG_CONFIG_PATH="/home/precice/.local/lib/pkgconfig:$PKG_CONFIG_PATH" -ENV CMAKE_PREFIX_PATH="/home/precice/.local:$CMAKE_PREFIX_PATH" USER root RUN apt-get -qq update && \ apt-get -qq install libarpack2-dev libspooles-dev libyaml-cpp-dev +ARG CALULIX_VERSION USER precice -ARG CALULIX_VERSION="2.20" -# Building fenics-adapter +#Download Calculix WORKDIR /home/precice RUN wget http://www.dhondt.de/ccx_${CALULIX_VERSION}.src.tar.bz2 && \ - tar xvjf ccx_${CALULIX_VERSION}.src.tar.bz2 && + tar xvjf ccx_${CALULIX_VERSION}.src.tar.bz2 && \ + rm -fv ccx_${CALULIX_VERSION}.src.tar.bz2 -ARG CALULIX_ADAPTER_REF=v2.20.0 -WORKDIR /opt/precice +ARG CALULIX_ADAPTER_REF +WORKDIR /home/precice RUN git clone --depth 1 --branch ${CALULIX_ADAPTER_REF} https://github.com/precice/calculix-adapter.git && \ cd calculix-adapter && \ - make CCX="/home/precice//CalculiX/ccx_${CALULIX_VERSION}/src" CCX_VERSION="${CALULIX_VERSION}" && \ - ln -s /opt/precice/calculix_source/current/src/ccx_preCICE /home/precice/.local/bin/ccx_preCICE + make CXX_VERSION=${CALULIX_VERSION} ADDITIONAL_FFLAGS="-std=legacy" -j $(nproc) && \ + ln -s /home/precice/calculix-adapter/bin/ccx_preCICE /home/precice/.local/bin/ccx_preCICE diff --git a/tools/tests/generate_reference_data.py b/tools/tests/generate_reference_data.py index c0452d78e..1d350eadd 100644 --- a/tools/tests/generate_reference_data.py +++ b/tools/tests/generate_reference_data.py @@ -5,7 +5,7 @@ from systemtests.SystemtestArguments import SystemtestArguments from systemtests.Systemtest import Systemtest from pathlib import Path -from typing import List, Tuple, Optional, Dict +from typing import List from paths import PRECICE_TESTS_DIR, PRECICE_TUTORIAL_DIR import hashlib from jinja2 import Environment, FileSystemLoader @@ -13,6 +13,7 @@ from datetime import datetime import logging from paths import PRECICE_TUTORIAL_DIR, PRECICE_TESTS_RUN_DIR, PRECICE_TESTS_DIR, PRECICE_REL_OUTPUT_DIR +import time def create_tar_gz(source_folder: Path, output_filename: Path): @@ -24,21 +25,14 @@ def render_reference_results_info( reference_results: List[ReferenceResult], arguments_used: SystemtestArguments, time: str): - def calculate_sha1(file_path: Path): - buffer_size = 65536 - sha1_hash = hashlib.sha1() - with open(file_path, "rb") as f: - while True: - data = f.read(buffer_size) - if not data: - break - sha1_hash.update(data) - return sha1_hash.hexdigest() + def sha256sum(filename): + with open(filename, 'rb', buffering=0) as f: + return hashlib.file_digest(f, 'sha256').hexdigest() files = [] for reference_result in reference_results: files.append({ - 'sha1': calculate_sha1(reference_result.path), + 'sha256': sha256sum(reference_result.path), 'time': time, 'name': reference_result.path.name, }) @@ -52,58 +46,73 @@ def calculate_sha1(file_path: Path): return template.render(render_dict) -parser = argparse.ArgumentParser(description='generate reference data') -parser.add_argument('--rundir', type=str, help='Directory to run the systemstests in.', - nargs='?', const=PRECICE_TESTS_RUN_DIR, default=PRECICE_TESTS_RUN_DIR) -# Parse the command-line arguments -args = parser.parse_args() - -run_directory = Path(args.rundir) - -available_tutorials = Tutorials.from_path(PRECICE_TUTORIAL_DIR) - -test_suites = TestSuites.from_yaml(PRECICE_TESTS_DIR / "tests.yaml", available_tutorials) - -# Read in parameters -build_args = SystemtestArguments.from_yaml(PRECICE_TESTS_DIR / "reference_versions.yaml") -systemtests_to_run = set() - -for test_suite in test_suites: - tutorials = test_suite.cases_of_tutorial.keys() - for tutorial in tutorials: - for case, reference_result in zip( - test_suite.cases_of_tutorial[tutorial], test_suite.reference_results[tutorial]): - systemtests_to_run.add( - Systemtest(tutorial, build_args, case, reference_result)) - - -reference_result_per_tutorial = {} -current_time_string = datetime.now().strftime('%Y-%m-%d %H:%M:%S') - - -logging.info(f"About to run the following tests {systemtests_to_run}") -for systemtest in systemtests_to_run: - result = systemtest.run_for_reference_results(run_directory) - if not result.success: - raise RuntimeError("Failed to execute {systemtest}") - reference_result_per_tutorial[systemtest.tutorial] = [] - -# Put the tar.gz in there -for systemtest in systemtests_to_run: - reference_result_folder = systemtest.get_system_test_dir() / PRECICE_REL_OUTPUT_DIR - reference_result_per_tutorial[systemtest.tutorial].append(systemtest.reference_result) - # create folder if needed - systemtest.reference_result.path.parent.mkdir(parents=True, exist_ok=True) - if reference_result_folder.exists(): - create_tar_gz(reference_result_folder, systemtest.reference_result.path) - else: - raise RuntimeError( - f"Error executing: \n {systemtest} \n Could not find result folder {reference_result_folder}\n Probably the tutorial did not run through properly. Please check corresponding logs") - -# write readme -for tutorial in reference_result_per_tutorial.keys(): - with open(tutorial.path / "reference_results.md", 'w') as file: - ref_results_info = render_reference_results_info( - reference_result_per_tutorial[tutorial], build_args, current_time_string) - logging.info(f"writing results for {tutorial.name}") - file.write(ref_results_info) +def main(): + + parser = argparse.ArgumentParser(description='Generate reference data for systemtests') + parser.add_argument('--rundir', type=str, help='Directory to run the systemstests in.', + nargs='?', const=PRECICE_TESTS_RUN_DIR, default=PRECICE_TESTS_RUN_DIR) + parser.add_argument('--log-level', choices=['DEBUG', 'INFO', 'WARNING', 'ERROR', 'CRITICAL'], + default='INFO', help='Set the logging level') + + args = parser.parse_args() + + logging.basicConfig(level=args.log_level, format='%(levelname)s: %(message)s') + + print(f"Using log-level: {args.log_level}") + + run_directory = Path(args.rundir) + + available_tutorials = Tutorials.from_path(PRECICE_TUTORIAL_DIR) + + test_suites = TestSuites.from_yaml(PRECICE_TESTS_DIR / "tests.yaml", available_tutorials) + + # Read in parameters + build_args = SystemtestArguments.from_yaml(PRECICE_TESTS_DIR / "reference_versions.yaml") + systemtests_to_run = set() + + for test_suite in test_suites: + tutorials = test_suite.cases_of_tutorial.keys() + for tutorial in tutorials: + for case, reference_result in zip( + test_suite.cases_of_tutorial[tutorial], test_suite.reference_results[tutorial]): + systemtests_to_run.add( + Systemtest(tutorial, build_args, case, reference_result)) + + reference_result_per_tutorial = {} + current_time_string = datetime.now().strftime('%Y-%m-%d %H:%M:%S') + + logging.info(f"About to run the following tests {systemtests_to_run}") + for number, systemtest in enumerate(systemtests_to_run): + logging.info(f"Started running {systemtest}, {number}/{len(systemtests_to_run)}") + t = time.perf_counter() + result = systemtest.run_for_reference_results(run_directory) + elapsed_time = time.perf_counter() - t + logging.info(f"Running {systemtest} took {elapsed_time} seconds") + if not result.success: + raise RuntimeError(f"Failed to execute {systemtest}") + reference_result_per_tutorial[systemtest.tutorial] = [] + + # Put the tar.gz in there + for systemtest in systemtests_to_run: + reference_result_folder = systemtest.get_system_test_dir() / PRECICE_REL_OUTPUT_DIR + reference_result_per_tutorial[systemtest.tutorial].append(systemtest.reference_result) + # create folder if needed + systemtest.reference_result.path.parent.mkdir(parents=True, exist_ok=True) + if reference_result_folder.exists(): + create_tar_gz(reference_result_folder, systemtest.reference_result.path) + else: + raise RuntimeError( + f"Error executing: \n {systemtest} \n Could not find result folder {reference_result_folder}\n Probably the tutorial did not run through properly. Please check corresponding logs") + + # write readme + for tutorial in reference_result_per_tutorial.keys(): + with open(tutorial.path / "reference_results.md", 'w') as file: + ref_results_info = render_reference_results_info( + reference_result_per_tutorial[tutorial], build_args, current_time_string) + logging.info(f"Writing results for {tutorial.name}") + file.write(ref_results_info) + logging.info(f"Done. Please make sure to manually have a look into the reference results before making a PR.") + + +if __name__ == '__main__': + main() diff --git a/tools/tests/print_case_combinations.py b/tools/tests/print_case_combinations.py index a3778c4cd..25e318918 100644 --- a/tools/tests/print_case_combinations.py +++ b/tools/tests/print_case_combinations.py @@ -1,16 +1,32 @@ import yaml -from metadata_parser.metdata import Tutorials, Components -from paths import PRECICE_TUTORIAL_DIR, PRECICE_TESTS_DIR +from metadata_parser.metdata import Tutorials +from paths import PRECICE_TUTORIAL_DIR -available_components = Components.from_yaml( - PRECICE_TESTS_DIR / "components.yaml") +import argparse +import logging -available_tutorials = Tutorials.from_path(PRECICE_TUTORIAL_DIR) -tutorials = {} -for tutorial in available_tutorials: - cases_combinations = [ - f"{combination}" for combination in tutorial.case_combinations] - tutorials[tutorial.path.name] = cases_combinations +def main(): + parser = argparse.ArgumentParser(description='Prints available Metadata for tutorials') + parser.add_argument('--log-level', choices=['DEBUG', 'INFO', 'WARNING', 'ERROR', 'CRITICAL'], + default='INFO', help='Set the logging level') + args = parser.parse_args() -print(yaml.dump(tutorials)) + # Configure logging based on the provided log level + logging.basicConfig(level=args.log_level, format='%(levelname)s: %(message)s') + + print(f"Using log-level: {args.log_level}") + + available_tutorials = Tutorials.from_path(PRECICE_TUTORIAL_DIR) + + tutorials = {} + for tutorial in available_tutorials: + cases_combinations = [ + f"{combination}" for combination in tutorial.case_combinations] + tutorials[tutorial.path.name] = cases_combinations + + print(yaml.dump(tutorials)) + + +if __name__ == '__main__': + main() diff --git a/tools/tests/print_metadata.py b/tools/tests/print_metadata.py index 5c568c841..500e549c9 100644 --- a/tools/tests/print_metadata.py +++ b/tools/tests/print_metadata.py @@ -1,7 +1,26 @@ from metadata_parser.metdata import Tutorials from paths import PRECICE_TUTORIAL_DIR -available_tutorials = Tutorials.from_path(PRECICE_TUTORIAL_DIR) -print("Fount the following tutorials read from the metadata.yaml") -for tutorial in available_tutorials: - print(tutorial) +import argparse +import logging + + +def main(): + parser = argparse.ArgumentParser(description='Prints available Metadata for tutorials') + parser.add_argument('--log-level', choices=['DEBUG', 'INFO', 'WARNING', 'ERROR', 'CRITICAL'], + default='INFO', help='Set the logging level') + args = parser.parse_args() + + # Configure logging based on the provided log level + logging.basicConfig(level=args.log_level, format='%(levelname)s: %(message)s') + + print(f"Using log-level: {args.log_level}") + + available_tutorials = Tutorials.from_path(PRECICE_TUTORIAL_DIR) + print("Fount the following tutorials read from the metadata.yaml") + for tutorial in available_tutorials: + print(tutorial) + + +if __name__ == '__main__': + main() diff --git a/tools/tests/print_test_suites.py b/tools/tests/print_test_suites.py index 95ccbcb60..6fc1e4039 100644 --- a/tools/tests/print_test_suites.py +++ b/tools/tests/print_test_suites.py @@ -1,11 +1,29 @@ -from metadata_parser.metdata import Tutorials, Components +from metadata_parser.metdata import Tutorials from systemtests.TestSuite import TestSuites from paths import PRECICE_TESTS_DIR, PRECICE_TUTORIAL_DIR -available_tutorials = Tutorials.from_path(PRECICE_TUTORIAL_DIR) -available_components = Components.from_yaml( - PRECICE_TESTS_DIR / "components.yaml") -available_testsuites = TestSuites.from_yaml( - PRECICE_TESTS_DIR / "tests.yaml", available_tutorials) -print(available_testsuites) +import argparse +import logging + + +def main(): + parser = argparse.ArgumentParser(description='Prints available Test Suites') + parser.add_argument('--log-level', choices=['DEBUG', 'INFO', 'WARNING', 'ERROR', 'CRITICAL'], + default='INFO', help='Set the logging level') + args = parser.parse_args() + + # Configure logging based on the provided log level + logging.basicConfig(level=args.log_level, format='%(levelname)s: %(message)s') + + print(f"Using log-level: {args.log_level}") + + available_tutorials = Tutorials.from_path(PRECICE_TUTORIAL_DIR) + available_testsuites = TestSuites.from_yaml( + PRECICE_TESTS_DIR / "tests.yaml", available_tutorials) + + print(available_testsuites) + + +if __name__ == '__main__': + main() diff --git a/tools/tests/reference_results.template b/tools/tests/reference_results.template index e4e1eb7f4..d711cd872 100644 --- a/tools/tests/reference_results.template +++ b/tools/tests/reference_results.template @@ -8,10 +8,10 @@ This file contains an overview of the results over the reference results as well ## List of files -| name | time | sha-1 | +| name | time | sha256 | |------|------|-------| {% for file in files -%} -| {{ file.name }} | {{ file.time }} | {{ file.sha1 }} | +| {{ file.name }} | {{ file.time }} | {{ file.sha256 }} | {% endfor %} ## List of arguments used to generate the files diff --git a/tools/tests/reference_versions.yaml b/tools/tests/reference_versions.yaml index 846557d37..f5c8be62a 100644 --- a/tools/tests/reference_versions.yaml +++ b/tools/tests/reference_versions.yaml @@ -1,13 +1,9 @@ -PRECICE_REF: "main" -OPENFOAM_EXECUTABLE: "openfoam2206" -OPENFOAM_ADAPTER_REF: "master" -PYTHON_BINDINGS_REF: "master" -FENICS_ADAPTER_REF: "master" -TUTORIALS_REF: "master" +PRECICE_REF: "v2.5.0" +OPENFOAM_EXECUTABLE: "openfoam2306" +OPENFOAM_ADAPTER_REF: "v1.2.3" +PYTHON_BINDINGS_REF: "v2.5.0.4" +FENICS_ADAPTER_REF: "v1.4.0" +TUTORIALS_REF: "v202211.0" PLATFORM: "ubuntu_2204" -#PRECICE_REF: "v2.5.0" -#OPENFOAM_EXECUTABLE: "openfoam2206" -#OPENFOAM_ADAPTER_REF: "v1.2.0" -#PYTHON_BINDINGS_REF: "v2.5.0.1" -#FENICS_ADAPTER_REF: "v1.4.0" -#TUTORIALS_REF: "v202211.0" \ No newline at end of file +CALULIX_VERSION: "2.20" +CALULIX_ADAPTER_REF: "v2.20.0" \ No newline at end of file diff --git a/tools/tests/systemtests.py b/tools/tests/systemtests.py index 69de229f8..dd8962088 100644 --- a/tools/tests/systemtests.py +++ b/tools/tests/systemtests.py @@ -6,73 +6,90 @@ from systemtests.TestSuite import TestSuites from metadata_parser.metdata import Tutorials, Case import logging - +import time from paths import PRECICE_TUTORIAL_DIR, PRECICE_TESTS_RUN_DIR, PRECICE_TESTS_DIR -parser = argparse.ArgumentParser(description='systemtest') - -# Add an argument for the components -parser.add_argument('--suites', type=str, - help='Comma-separated test-suites to execute') -parser.add_argument( - '--build_args', - type=str, - help='Comma-separated list of arguments provided to the components like openfoam:2102,pythonbindings:latest') -parser.add_argument('--rundir', type=str, help='Directory to run the systemstests in.', - nargs='?', const=PRECICE_TESTS_RUN_DIR, default=PRECICE_TESTS_RUN_DIR) - -# Parse the command-line arguments -args = parser.parse_args() -systemtests_to_run = [] -available_tutorials = Tutorials.from_path(PRECICE_TUTORIAL_DIR) - - -build_args = SystemtestArguments.from_args(args.build_args) -run_directory = Path(args.rundir) -if args.suites: - test_suites_requested = args.suites.split(',') - available_testsuites = TestSuites.from_yaml( - PRECICE_TESTS_DIR / "tests.yaml", available_tutorials) - test_suites_to_execute = [] - for test_suite_requested in test_suites_requested: - test_suite_found = available_testsuites.get_by_name( - test_suite_requested) - if not test_suite_found: - logging.error(f"Did not find the testsuite with name {test_suite_requested}") + +def main(): + parser = argparse.ArgumentParser(description='systemtest') + + # Add an argument for the components + parser.add_argument('--suites', type=str, + help='Comma-separated test-suites to execute') + parser.add_argument( + '--build_args', + type=str, + help='Comma-separated list of arguments provided to the components like openfoam:2102,pythonbindings:latest') + parser.add_argument('--rundir', type=str, help='Directory to run the systemstests in.', + nargs='?', const=PRECICE_TESTS_RUN_DIR, default=PRECICE_TESTS_RUN_DIR) + + parser.add_argument('--log-level', choices=['DEBUG', 'INFO', 'WARNING', 'ERROR', 'CRITICAL'], + default='INFO', help='Set the logging level') + + # Parse the command-line arguments + args = parser.parse_args() + + # Configure logging based on the provided log level + logging.basicConfig(level=args.log_level, format='%(levelname)s: %(message)s') + + print(f"Using log-level: {args.log_level}") + + systemtests_to_run = [] + available_tutorials = Tutorials.from_path(PRECICE_TUTORIAL_DIR) + + build_args = SystemtestArguments.from_args(args.build_args) + run_directory = Path(args.rundir) + if args.suites: + test_suites_requested = args.suites.split(',') + available_testsuites = TestSuites.from_yaml( + PRECICE_TESTS_DIR / "tests.yaml", available_tutorials) + test_suites_to_execute = [] + for test_suite_requested in test_suites_requested: + test_suite_found = available_testsuites.get_by_name( + test_suite_requested) + if not test_suite_found: + logging.error(f"Did not find the testsuite with name {test_suite_requested}") + else: + test_suites_to_execute.append(test_suite_found) + if not test_suites_to_execute: + raise RuntimeError( + f"No matching test suites with names {test_suites_requested} found. Use print_test_suites.py to get an overview") + # now convert the test_suites into systemtests + for test_suite in test_suites_to_execute: + tutorials = test_suite.cases_of_tutorial.keys() + for tutorial in tutorials: + for case, reference_result in zip( + test_suite.cases_of_tutorial[tutorial], test_suite.reference_results[tutorial]): + systemtests_to_run.append( + Systemtest(tutorial, build_args, case, reference_result)) + + if not systemtests_to_run: + raise RuntimeError("Did not find any Systemtests to execute.") + + logging.info(f"About to run the following systemtest in the directory {run_directory}:\n {systemtests_to_run}") + + results = [] + for number, systemtest in enumerate(systemtests_to_run): + logging.info(f"Started running {systemtest}, {number}/{len(systemtests_to_run)}") + t = time.perf_counter() + result = systemtest.run(run_directory) + elapsed_time = time.perf_counter() - t + logging.info(f"Running {systemtest} took {elapsed_time} seconds") + results.append(result) + + system_test_success = True + for result in results: + if not result.success: + logging.error(f"Failed to run {result.systemtest}") + system_test_success = False else: - test_suites_to_execute.append(test_suite_found) - if not test_suites_to_execute: - raise RuntimeError( - f"No matching test suites with names {test_suites_requested} found. Use print_test_suites.py to get an overview") - # now convert the test_suites into systemtests - for test_suite in test_suites_to_execute: - tutorials = test_suite.cases_of_tutorial.keys() - for tutorial in tutorials: - for case, reference_result in zip( - test_suite.cases_of_tutorial[tutorial], test_suite.reference_results[tutorial]): - systemtests_to_run.append( - Systemtest(tutorial, build_args, case, reference_result)) - - -if not systemtests_to_run: - raise RuntimeError("Did not find any Systemtests to execute.") - - -logging.info(f"About to run the following systemtest in the directory {run_directory}: \n{systemtests_to_run}") - -results = [] -for systemtest in systemtests_to_run: - results.append(systemtest.run(run_directory)) - -system_test_success = True -for result in results: - if not result.success: - logging.error(f"Failed to run {result.systemtest}") - system_test_success = False + logging.info(f"Success running {result.systemtest}") + + if system_test_success: + exit(0) else: - logging.info(f"Success running {result.systemtest}") + exit(1) + -if system_test_success: - exit(0) -else: - exit(1) +if __name__ == '__main__': + main() diff --git a/tools/tests/systemtests/Systemtest.py b/tools/tests/systemtests/Systemtest.py index b73a07983..481b478e4 100644 --- a/tools/tests/systemtests/Systemtest.py +++ b/tools/tests/systemtests/Systemtest.py @@ -36,9 +36,6 @@ def slugify(value, allow_unicode=False): return re.sub(r'[-\s]+', '-', value).strip('-_') -system_test_dir = Path(__file__).parent.parent - - class Systemtest: pass @@ -67,6 +64,9 @@ class SystemtestResult: systemtest: Systemtest +GLOBAL_TIMEOUT = 360 + + @dataclass class Systemtest: """ @@ -130,7 +130,7 @@ def __get_docker_services(self) -> Dict[str, str]: A dictionary of rendered services per case name. """ try: - plaform_requested = self.arguments.get("PLATFORM") + plaform_requested = self.params_to_use.get("PLATFORM") except Exception as exc: raise KeyError("Please specify a PLATFORM argument") from exc @@ -149,7 +149,7 @@ def render_service_template_per_case(case: Case, params_to_use: Dict[str, str]) 'run': case.run_cmd, 'dockerfile_context': self.dockerfile_context, } - jinja_env = Environment(loader=FileSystemLoader(system_test_dir)) + jinja_env = Environment(loader=FileSystemLoader(PRECICE_TESTS_DIR)) template = jinja_env.get_template(case.component.template) return template.render(render_dict) @@ -169,7 +169,7 @@ def __get_docker_compose_file(self): 'dockerfile_context': self.dockerfile_context, 'precice_output_folder': PRECICE_REL_OUTPUT_DIR, } - jinja_env = Environment(loader=FileSystemLoader(system_test_dir)) + jinja_env = Environment(loader=FileSystemLoader(PRECICE_TESTS_DIR)) template = jinja_env.get_template("docker-compose.template.yaml") return template.render(render_dict) @@ -180,7 +180,7 @@ def __get_field_compare_compose_file(self): 'precice_output_folder': PRECICE_REL_OUTPUT_DIR, 'reference_output_folder': PRECICE_REL_REFERENCE_DIR + "/" + self.reference_result.path.name.replace(".tar.gz", ""), } - jinja_env = Environment(loader=FileSystemLoader(system_test_dir)) + jinja_env = Environment(loader=FileSystemLoader(PRECICE_TESTS_DIR)) template = jinja_env.get_template( "docker-compose.field_compare.template.yaml") return template.render(render_dict) @@ -193,10 +193,10 @@ def _get_git_ref(self, repository: Path, abbrev_ref=False) -> Optional[str]: "rev-parse", "--abbrev-ref" if abbrev_ref else "HEAD"], stdout=subprocess.PIPE, - stderr=subprocess.PIPE, text=True, check=True) + stderr=subprocess.PIPE, text=True, check=True, timeout=60) current_ref = result.stdout.strip() return current_ref - except subprocess.CalledProcessError as e: + except Exception as e: raise RuntimeError(f"An error occurred while getting the current Git ref: {e}") from e def _checkout_ref_in_subfolder(self, repository: Path, subfolder: Path, ref: str): @@ -206,9 +206,9 @@ def _checkout_ref_in_subfolder(self, repository: Path, subfolder: Path, ref: str "-C", repository.resolve(), "checkout", ref, "--", subfolder.resolve() - ], check=True) + ], check=True, timeout=60) if result.returncode != 0: - raise RuntimeError(f"git command return code {result.returncode}") + raise RuntimeError(f"git command returned code {result.returncode}") except Exception as e: raise RuntimeError(f"An error occurred while checking out '{ref}' for folder '{repository}': {e}") @@ -220,7 +220,7 @@ def __copy_tutorial_into_directory(self, run_directory: Path): current_time_string = datetime.now().strftime('%Y-%m-%d %H:%M:%S') self.run_directory = run_directory current_ref = self._get_git_ref(PRECICE_TUTORIAL_DIR) - ref_requested = self.arguments.get("TUTORIALS_REF") + ref_requested = self.params_to_use.get("TUTORIALS_REF") if ref_requested: logging.debug(f"Checking out tutorials {ref_requested} before copying") self._checkout_ref_in_subfolder(PRECICE_TUTORIAL_DIR, self.tutorial.path, ref_requested) @@ -231,10 +231,9 @@ def __copy_tutorial_into_directory(self, run_directory: Path): self.system_test_dir = destination shutil.copytree(src, destination) - with open(destination / "tutorials_ref", 'w') as file: - file.write(ref_requested) - if ref_requested: + with open(destination / "tutorials_ref", 'w') as file: + file.write(ref_requested) self._checkout_ref_in_subfolder(PRECICE_TUTORIAL_DIR, self.tutorial.path, current_ref) def __copy_tools(self, run_directory: Path): @@ -243,7 +242,7 @@ def __copy_tools(self, run_directory: Path): try: shutil.copytree(src, destination) except Exception as e: - logging.debug("tools are already copied: ", e) + logging.debug(f"tools are already copied: {e} ") def __put_gitignore(self, run_directory: Path): # Create the .gitignore file with a single asterisk @@ -302,24 +301,24 @@ def _run_field_compare(self): 'field-compare'], stdout=subprocess.PIPE, stderr=subprocess.PIPE, + start_new_session=True, cwd=self.system_test_dir) - # Read the output in real-time - while True: - output = process.stdout.readline().decode() - if output == '' and process.poll() is not None: - break - if output: - stdout_data.append(output) - logging.debug(output, end='') - - # Capture remaining output - stdout, stderr = process.communicate() + try: + stdout, stderr = process.communicate(timeout=GLOBAL_TIMEOUT) + except KeyboardInterrupt as k: + process.kill() + # process.send_signal(9) + raise KeyboardInterrupt from k + except Exception as e: + logging.critical( + f"Systemtest {self} had serious issues executin the docker compose command about to kill the docker compose command. Please check the logs! {e}") + process.kill() + stdout, stderr = process.communicate() stdout_data.extend(stdout.decode().splitlines()) stderr_data.extend(stderr.decode().splitlines()) - - exit_code = process.wait() - return FieldCompareResult(exit_code, stdout_data, stderr_data, self) + process.poll() + return FieldCompareResult(process.returncode, stdout_data, stderr_data, self) except Exception as e: logging.CRITICAL("Error executing docker compose command:", e) return FieldCompareResult(1, stdout_data, stderr_data, self) @@ -347,36 +346,46 @@ def _run_tutorial(self): "--build"], stdout=subprocess.PIPE, stderr=subprocess.PIPE, + start_new_session=True, cwd=self.system_test_dir) - # Read the output in real-time - while True: - output = process.stdout.readline().decode() - if output == '' and process.poll() is not None: - break - if output: - stdout_data.append(output) - logging.debug(output, end='') - - # Capture remaining output - stdout, stderr = process.communicate() + try: + stdout, stderr = process.communicate(timeout=GLOBAL_TIMEOUT) + except KeyboardInterrupt as k: + process.kill() + # process.send_signal(9) + raise KeyboardInterrupt from k + except Exception as e: + logging.critical( + f"Systemtest {self} had serious issues executin the docker compose command about to kill the docker compose command. Please check the logs! {e}") + process.kill() + stdout, stderr = process.communicate() + stdout_data.extend(stdout.decode().splitlines()) stderr_data.extend(stderr.decode().splitlines()) - exit_code = process.wait() - return DockerComposeResult(exit_code, stdout_data, stderr_data, self) + return DockerComposeResult(process.returncode, stdout_data, stderr_data, self) except Exception as e: - logging.critical("Error executing docker compose command:", e) + logging.critical(f"Error executing docker compose command: {e}") return DockerComposeResult(1, stdout_data, stderr_data, self) def __repr__(self): return f"{self.tutorial.name} {self.case_combination}" def __handle_docker_compose_failure(self, result: DockerComposeResult): - logging.critical("Docker Compose failed, skipping fieldcompare") + with open(self.system_test_dir / "stdout.log", 'w') as stdout_file: + stdout_file.write("\n".join(result.stdout_data)) + with open(self.system_test_dir / "stderr.log", 'w') as stderr_file: + stderr_file.write("\n".join(result.stderr_data)) + + logging.critical("Docker Compose failed, skipping fieldcompare and writing stdout.log and stderr.log") def __handle_field_compare_failure(self, result: FieldCompareResult): - logging.error("Fieldcompare failed") + with open(self.system_test_dir / "stdout.log", 'w') as stdout_file: + stdout_file.write("\n".join(result.stdout_data)) + with open(self.system_test_dir / "stderr.log", 'w') as stderr_file: + stderr_file.write("\n".join(result.stderr_data)) + logging.error("Fieldcompare failed, writing stdout.log and stderr.log") def run(self, run_directory: Path): """ @@ -401,7 +410,7 @@ def run(self, run_directory: Path): fieldcompare_result = self._run_field_compare() std_out.extend(fieldcompare_result.stdout_data) std_err.extend(fieldcompare_result.stderr_data) - if fieldcompare_result.exit_code != 1: + if fieldcompare_result.exit_code != 0: self.__handle_field_compare_failure(fieldcompare_result) return SystemtestResult(False, std_out, std_err, self) diff --git a/tools/tests/tests.yaml b/tools/tests/tests.yaml index 2efe53188..827eae38e 100644 --- a/tools/tests/tests.yaml +++ b/tools/tests/tests.yaml @@ -17,11 +17,9 @@ test_suites: tutorials: - path: flow-over-heated-plate case_combination: - - fluid-openfoam - solid-fenics reference_result: ./flow-over-heated-plate/reference-data/fluid-openfoam_solid-fenics.tar.gz - reference_time: nutils_test: tutorials: - path: flow-over-heated-plate @@ -29,10 +27,11 @@ test_suites: - fluid-openfoam - solid-nutils reference_result: ./flow-over-heated-plate/reference-data/fluid-openfoam_solid-nutils.tar.gz - nutils_fenics_test: + calculix_test: tutorials: - path: perpendicular-flap case_combination: - - fluid-nutils - - solid-fenics - reference_result: ./perpendicular-flap/reference-data/fluid-nutils_solid-nutils.tar.gz \ No newline at end of file + - fluid-openfoam + - solid-calculix + reference_result: ./perpendicular-flap/reference-data/fluid-openfoam_solid-calculix.tar.gz + timeout: \ No newline at end of file From 6a4567eedbbfdd7aa622cb321062342e91bb782b Mon Sep 17 00:00:00 2001 From: Valentin Seitz Date: Mon, 4 Sep 2023 21:32:25 +0200 Subject: [PATCH 13/19] Split building docker and running tutorial --- tools/tests/systemtests/Systemtest.py | 86 ++++++++++++++++++++------- 1 file changed, 65 insertions(+), 21 deletions(-) diff --git a/tools/tests/systemtests/Systemtest.py b/tools/tests/systemtests/Systemtest.py index 481b478e4..2821e601f 100644 --- a/tools/tests/systemtests/Systemtest.py +++ b/tools/tests/systemtests/Systemtest.py @@ -323,6 +323,50 @@ def _run_field_compare(self): logging.CRITICAL("Error executing docker compose command:", e) return FieldCompareResult(1, stdout_data, stderr_data, self) + def _build_docker(self): + """ + Builds the docker image + """ + logging.debug(f"Building docker image for {self}") + docker_compose_content = self.__get_docker_compose_file() + with open(self.system_test_dir / "docker-compose.tutorial.yaml", 'w') as file: + file.write(docker_compose_content) + + stdout_data = [] + stderr_data = [] + + try: + # Execute docker-compose command + process = subprocess.Popen(['docker', + 'compose', + '--file', + 'docker-compose.tutorial.yaml', + 'build'], + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + start_new_session=True, + cwd=self.system_test_dir) + + try: + stdout, stderr = process.communicate() + except KeyboardInterrupt as k: + process.kill() + # process.send_signal(9) + raise KeyboardInterrupt from k + except Exception as e: + logging.critical( + f"systemtest {self} had serious issues building the docker images via the `docker compose build` command. About to kill the docker compose command. Please check the logs! {e}") + process.kill() + stdout, stderr = process.communicate() + + stdout_data.extend(stdout.decode().splitlines()) + stderr_data.extend(stderr.decode().splitlines()) + + return DockerComposeResult(process.returncode, stdout_data, stderr_data, self) + except Exception as e: + logging.critical(f"Error executing docker compose build command: {e}") + return DockerComposeResult(1, stdout_data, stderr_data, self) + def _run_tutorial(self): """ Runs precice couple @@ -330,20 +374,17 @@ def _run_tutorial(self): Returns: A DockerComposeResult object containing the state. """ - docker_compose_content = self.__get_docker_compose_file() + + logging.debug(f"Running tutorial {self}") stdout_data = [] stderr_data = [] - - with open(self.system_test_dir / "docker-compose.tutorial.yaml", 'w') as file: - file.write(docker_compose_content) try: # Execute docker-compose command process = subprocess.Popen(['docker', 'compose', '--file', 'docker-compose.tutorial.yaml', - 'up', - "--build"], + 'up'], stdout=subprocess.PIPE, stderr=subprocess.PIPE, start_new_session=True, @@ -366,26 +407,17 @@ def _run_tutorial(self): return DockerComposeResult(process.returncode, stdout_data, stderr_data, self) except Exception as e: - logging.critical(f"Error executing docker compose command: {e}") + logging.critical(f"Error executing docker compose up command: {e}") return DockerComposeResult(1, stdout_data, stderr_data, self) def __repr__(self): return f"{self.tutorial.name} {self.case_combination}" - def __handle_docker_compose_failure(self, result: DockerComposeResult): + def __write_logs(self, stdout_data: List[str], stderr_data: List[str]): with open(self.system_test_dir / "stdout.log", 'w') as stdout_file: - stdout_file.write("\n".join(result.stdout_data)) + stdout_file.write("\n".join(stdout_data)) with open(self.system_test_dir / "stderr.log", 'w') as stderr_file: - stderr_file.write("\n".join(result.stderr_data)) - - logging.critical("Docker Compose failed, skipping fieldcompare and writing stdout.log and stderr.log") - - def __handle_field_compare_failure(self, result: FieldCompareResult): - with open(self.system_test_dir / "stdout.log", 'w') as stdout_file: - stdout_file.write("\n".join(result.stdout_data)) - with open(self.system_test_dir / "stderr.log", 'w') as stderr_file: - stderr_file.write("\n".join(result.stderr_data)) - logging.error("Fieldcompare failed, writing stdout.log and stderr.log") + stderr_file.write("\n".join(stderr_data)) def run(self, run_directory: Path): """ @@ -400,21 +432,33 @@ def run(self, run_directory: Path): self.env["UID"] = uid self.env["GID"] = gid self.__write_env_file() + + docker_build_result = self._build_docker() + std_out.extend(docker_build_result.stdout_data) + std_err.extend(docker_build_result.stderr_data) + if docker_build_result.exit_code != 0: + self.__write_logs(std_out, std_err) + logging.critical(f"Could not build the docker images, {self} failed") + return SystemtestResult(False, std_out, std_err, self) + docker_compose_result = self._run_tutorial() std_out.extend(docker_compose_result.stdout_data) std_err.extend(docker_compose_result.stderr_data) if docker_compose_result.exit_code != 0: - self.__handle_docker_compose_failure(docker_compose_result) + self.__write_logs(std_out, std_err) + logging.critical(f"Could not run the tutorial, {self} failed") return SystemtestResult(False, std_out, std_err, self) fieldcompare_result = self._run_field_compare() std_out.extend(fieldcompare_result.stdout_data) std_err.extend(fieldcompare_result.stderr_data) if fieldcompare_result.exit_code != 0: - self.__handle_field_compare_failure(fieldcompare_result) + self.__write_logs(std_out, std_err) + logging.critical(f"Fieldcompare returned non zero exit code, therefore {self} failed") return SystemtestResult(False, std_out, std_err, self) # self.__cleanup() + self.__write_logs(std_out, std_err) return SystemtestResult(True, std_out, std_err, self) def run_for_reference_results(self, run_directory: Path): From bf7fb5d490ba6ad4d59b902bfd153f0f3c39cbde Mon Sep 17 00:00:00 2001 From: Valentin Seitz Date: Mon, 4 Sep 2023 22:58:58 +0200 Subject: [PATCH 14/19] adopt to requested chnages: - fallow-arguments vs std-legacy - no nutils adapter, just install nutils --- tools/tests/dockerfiles/ubuntu_2204/Dockerfile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/tests/dockerfiles/ubuntu_2204/Dockerfile b/tools/tests/dockerfiles/ubuntu_2204/Dockerfile index f12b7af4d..3f34db82e 100644 --- a/tools/tests/dockerfiles/ubuntu_2204/Dockerfile +++ b/tools/tests/dockerfiles/ubuntu_2204/Dockerfile @@ -93,7 +93,7 @@ RUN pip3 install --user git+https://github.com/precice/fenics-adapter.git@${FENI FROM precice_dependecies as nutils_adapter COPY --from=python_bindings /home/precice/.local /home/precice/.local USER precice -# Building fenics-adapter +# Installing nutils - There is no adapter RUN pip3 install --user nutils @@ -114,5 +114,5 @@ ARG CALULIX_ADAPTER_REF WORKDIR /home/precice RUN git clone --depth 1 --branch ${CALULIX_ADAPTER_REF} https://github.com/precice/calculix-adapter.git && \ cd calculix-adapter && \ - make CXX_VERSION=${CALULIX_VERSION} ADDITIONAL_FFLAGS="-std=legacy" -j $(nproc) && \ + make CXX_VERSION=${CALULIX_VERSION} ADDITIONAL_FFLAGS="-fallow-argument-mismatch" -j $(nproc) && \ ln -s /home/precice/calculix-adapter/bin/ccx_preCICE /home/precice/.local/bin/ccx_preCICE From 9b57fab729270e6fe3aebd24f08d30b96889dfa4 Mon Sep 17 00:00:00 2001 From: Valentin Seitz Date: Mon, 4 Sep 2023 23:49:19 +0200 Subject: [PATCH 15/19] - Adopt .md to .metadata - generate new reference results --- .../reference-data/fluid-openfoam_solid-fenics.tar.gz | 4 ++-- .../reference-data/fluid-openfoam_solid-nutils.tar.gz | 4 ++-- .../reference-data/fluid-openfoam_solid-openfoam.tar.gz | 4 ++-- .../{reference_results.md => reference_results.metadata} | 6 +++--- .../reference-data/fluid-openfoam_solid-calculix.tar.gz | 4 ++-- .../{reference_results.md => reference_results.metadata} | 2 +- tools/tests/generate_reference_data.py | 4 ++-- ...results.template => reference_results.metadata.template} | 0 8 files changed, 14 insertions(+), 14 deletions(-) rename flow-over-heated-plate/{reference_results.md => reference_results.metadata} (64%) rename perpendicular-flap/{reference_results.md => reference_results.metadata} (84%) rename tools/tests/{reference_results.template => reference_results.metadata.template} (100%) diff --git a/flow-over-heated-plate/reference-data/fluid-openfoam_solid-fenics.tar.gz b/flow-over-heated-plate/reference-data/fluid-openfoam_solid-fenics.tar.gz index 57d94e61f..fd47ecc01 100644 --- a/flow-over-heated-plate/reference-data/fluid-openfoam_solid-fenics.tar.gz +++ b/flow-over-heated-plate/reference-data/fluid-openfoam_solid-fenics.tar.gz @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5eb3653447273dc6d16bd1066db6fd8537d7af32b520ba5e894d4abfad7fd5c8 -size 778129 +oid sha256:2565ffc51c8d80fab06ccdda33f62efceb6cdc03318998f5adc9ed0ac84acac2 +size 777932 diff --git a/flow-over-heated-plate/reference-data/fluid-openfoam_solid-nutils.tar.gz b/flow-over-heated-plate/reference-data/fluid-openfoam_solid-nutils.tar.gz index 2465b69fb..9c773bcdf 100644 --- a/flow-over-heated-plate/reference-data/fluid-openfoam_solid-nutils.tar.gz +++ b/flow-over-heated-plate/reference-data/fluid-openfoam_solid-nutils.tar.gz @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:cabb7a8283289d7a2222a996432b72bbfad0cc8514562e01d0426b1e5fc05b64 -size 532514 +oid sha256:8b3157902d3ad78593c5471a3a94dd5559fe6970e4cb54658b22ffd270c00297 +size 532549 diff --git a/flow-over-heated-plate/reference-data/fluid-openfoam_solid-openfoam.tar.gz b/flow-over-heated-plate/reference-data/fluid-openfoam_solid-openfoam.tar.gz index 36fc19592..ee340cd80 100644 --- a/flow-over-heated-plate/reference-data/fluid-openfoam_solid-openfoam.tar.gz +++ b/flow-over-heated-plate/reference-data/fluid-openfoam_solid-openfoam.tar.gz @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:21058f307ccba7531a99c820daf6674b47a7bc1c3a7f40829126d20c41779c43 -size 498330 +oid sha256:c29989e0118ade759e7313330aa8d3d900c660c404eaacd529e979aae6b899c7 +size 498432 diff --git a/flow-over-heated-plate/reference_results.md b/flow-over-heated-plate/reference_results.metadata similarity index 64% rename from flow-over-heated-plate/reference_results.md rename to flow-over-heated-plate/reference_results.metadata index 2c3c848c0..640389b49 100644 --- a/flow-over-heated-plate/reference_results.md +++ b/flow-over-heated-plate/reference_results.metadata @@ -10,9 +10,9 @@ This file contains an overview of the results over the reference results as well | name | time | sha256 | |------|------|-------| -| fluid-openfoam_solid-openfoam.tar.gz | 2023-08-28 23:42:54 | 21058f307ccba7531a99c820daf6674b47a7bc1c3a7f40829126d20c41779c43 | -| fluid-openfoam_solid-nutils.tar.gz | 2023-08-28 23:42:54 | cabb7a8283289d7a2222a996432b72bbfad0cc8514562e01d0426b1e5fc05b64 | -| fluid-openfoam_solid-fenics.tar.gz | 2023-08-28 23:42:54 | 5eb3653447273dc6d16bd1066db6fd8537d7af32b520ba5e894d4abfad7fd5c8 | +| fluid-openfoam_solid-nutils.tar.gz | 2023-09-04 23:41:09 | 8b3157902d3ad78593c5471a3a94dd5559fe6970e4cb54658b22ffd270c00297 | +| fluid-openfoam_solid-fenics.tar.gz | 2023-09-04 23:41:09 | 2565ffc51c8d80fab06ccdda33f62efceb6cdc03318998f5adc9ed0ac84acac2 | +| fluid-openfoam_solid-openfoam.tar.gz | 2023-09-04 23:41:09 | c29989e0118ade759e7313330aa8d3d900c660c404eaacd529e979aae6b899c7 | ## List of arguments used to generate the files diff --git a/perpendicular-flap/reference-data/fluid-openfoam_solid-calculix.tar.gz b/perpendicular-flap/reference-data/fluid-openfoam_solid-calculix.tar.gz index 070c78f5f..63d4135f6 100644 --- a/perpendicular-flap/reference-data/fluid-openfoam_solid-calculix.tar.gz +++ b/perpendicular-flap/reference-data/fluid-openfoam_solid-calculix.tar.gz @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:35686e4cb9dd8d1b58efd1d17fd63db4dba75fa9b650b2ec9bceca1a71951c04 -size 13561579 +oid sha256:596fe1aec3f72fa194c37c485688dea4e308544e3cd773d7c815d6e27c4e55a8 +size 13561235 diff --git a/perpendicular-flap/reference_results.md b/perpendicular-flap/reference_results.metadata similarity index 84% rename from perpendicular-flap/reference_results.md rename to perpendicular-flap/reference_results.metadata index d683c20cc..1255609aa 100644 --- a/perpendicular-flap/reference_results.md +++ b/perpendicular-flap/reference_results.metadata @@ -10,7 +10,7 @@ This file contains an overview of the results over the reference results as well | name | time | sha256 | |------|------|-------| -| fluid-openfoam_solid-calculix.tar.gz | 2023-08-28 23:42:54 | 35686e4cb9dd8d1b58efd1d17fd63db4dba75fa9b650b2ec9bceca1a71951c04 | +| fluid-openfoam_solid-calculix.tar.gz | 2023-09-04 23:41:09 | 596fe1aec3f72fa194c37c485688dea4e308544e3cd773d7c815d6e27c4e55a8 | ## List of arguments used to generate the files diff --git a/tools/tests/generate_reference_data.py b/tools/tests/generate_reference_data.py index 1d350eadd..ea2457984 100644 --- a/tools/tests/generate_reference_data.py +++ b/tools/tests/generate_reference_data.py @@ -42,7 +42,7 @@ def sha256sum(filename): 'files': files } jinja_env = Environment(loader=FileSystemLoader(PRECICE_TESTS_DIR)) - template = jinja_env.get_template("reference_results.template") + template = jinja_env.get_template("reference_results.metadata.template") return template.render(render_dict) @@ -106,7 +106,7 @@ def main(): # write readme for tutorial in reference_result_per_tutorial.keys(): - with open(tutorial.path / "reference_results.md", 'w') as file: + with open(tutorial.path / "reference_results.metadata", 'w') as file: ref_results_info = render_reference_results_info( reference_result_per_tutorial[tutorial], build_args, current_time_string) logging.info(f"Writing results for {tutorial.name}") diff --git a/tools/tests/reference_results.template b/tools/tests/reference_results.metadata.template similarity index 100% rename from tools/tests/reference_results.template rename to tools/tests/reference_results.metadata.template From 92f4ece8eb34deddc990a0456994d67316c8ad09 Mon Sep 17 00:00:00 2001 From: Valentin Seitz Date: Mon, 4 Sep 2023 23:50:02 +0200 Subject: [PATCH 16/19] - added overview table --- tools/tests/systemtests.py | 3 +- tools/tests/systemtests/Systemtest.py | 139 +++++++++++++++++++------- 2 files changed, 103 insertions(+), 39 deletions(-) diff --git a/tools/tests/systemtests.py b/tools/tests/systemtests.py index dd8962088..7a57bbde0 100644 --- a/tools/tests/systemtests.py +++ b/tools/tests/systemtests.py @@ -2,7 +2,7 @@ import argparse from pathlib import Path from systemtests.SystemtestArguments import SystemtestArguments -from systemtests.Systemtest import Systemtest +from systemtests.Systemtest import Systemtest, display_systemtestresults_as_table from systemtests.TestSuite import TestSuites from metadata_parser.metdata import Tutorials, Case import logging @@ -85,6 +85,7 @@ def main(): else: logging.info(f"Success running {result.systemtest}") + display_systemtestresults_as_table(results) if system_test_success: exit(0) else: diff --git a/tools/tests/systemtests/Systemtest.py b/tools/tests/systemtests/Systemtest.py index 2821e601f..492a71a77 100644 --- a/tools/tests/systemtests/Systemtest.py +++ b/tools/tests/systemtests/Systemtest.py @@ -1,4 +1,3 @@ -import os import subprocess from typing import List, Dict, Optional from jinja2 import Environment, FileSystemLoader @@ -12,12 +11,16 @@ from datetime import datetime import tarfile +import time import unicodedata import re import logging +GLOBAL_TIMEOUT = 360 + + def slugify(value, allow_unicode=False): """ Taken from https://github.com/django/django/blob/master/django/utils/text.py @@ -46,6 +49,7 @@ class DockerComposeResult: stdout_data: List[str] stderr_data: List[str] systemtest: Systemtest + runtime: float # in seconds @dataclass @@ -54,6 +58,7 @@ class FieldCompareResult: stdout_data: List[str] stderr_data: List[str] systemtest: Systemtest + runtime: float # in seconds @dataclass @@ -62,9 +67,32 @@ class SystemtestResult: stdout_data: List[str] stderr_data: List[str] systemtest: Systemtest + build_time: float # in seconds + solver_time: float # in seconds + fieldcompare_time: float # in seconds -GLOBAL_TIMEOUT = 360 +def display_systemtestresults_as_table(results: List[SystemtestResult]): + """ + Prints the result in a nice tabluated way to get an easy overview + """ + def _get_length_of_name(results: List[SystemtestResult]) -> int: + return max(len(str(result.systemtest)) for result in results) + + max_name_length = _get_length_of_name(results) + + header = f"| {'systemtest':<{max_name_length + 2}} | {'success':^7} | {'building time [s]':^17} | {'solver time [s]':^15} | {'fieldcompare time [s]':^21} |" + separator = "+-" + "-" * (max_name_length + 2) + \ + "-+---------+-------------------+-----------------+-----------------------+" + + print(separator) + print(header) + print(separator) + + for result in results: + row = f"| {str(result.systemtest):<{max_name_length + 2}} | {result.success:^7} | {result.build_time:^17.2f} | {result.solver_time:^15.2f} | {result.fieldcompare_time:^21.2f} |" + print(row) + print(separator) @dataclass @@ -283,6 +311,8 @@ def _run_field_compare(self): Returns: A SystemtestResult object containing the state. """ + logging.debug(f"Running fieldcompare for {self}") + time_start = time.perf_counter() self.__unpack_reference_results() docker_compose_content = self.__get_field_compare_compose_file() stdout_data = [] @@ -318,16 +348,19 @@ def _run_field_compare(self): stdout_data.extend(stdout.decode().splitlines()) stderr_data.extend(stderr.decode().splitlines()) process.poll() - return FieldCompareResult(process.returncode, stdout_data, stderr_data, self) + elapsed_time = time.perf_counter() - time_start + return FieldCompareResult(process.returncode, stdout_data, stderr_data, self, elapsed_time) except Exception as e: logging.CRITICAL("Error executing docker compose command:", e) - return FieldCompareResult(1, stdout_data, stderr_data, self) + elapsed_time = time.perf_counter() - time_start + return FieldCompareResult(1, stdout_data, stderr_data, self, elapsed_time) def _build_docker(self): """ Builds the docker image """ logging.debug(f"Building docker image for {self}") + time_start = time.perf_counter() docker_compose_content = self.__get_docker_compose_file() with open(self.system_test_dir / "docker-compose.tutorial.yaml", 'w') as file: file.write(docker_compose_content) @@ -361,11 +394,12 @@ def _build_docker(self): stdout_data.extend(stdout.decode().splitlines()) stderr_data.extend(stderr.decode().splitlines()) - - return DockerComposeResult(process.returncode, stdout_data, stderr_data, self) + elapsed_time = time.perf_counter() - time_start + return DockerComposeResult(process.returncode, stdout_data, stderr_data, self, elapsed_time) except Exception as e: logging.critical(f"Error executing docker compose build command: {e}") - return DockerComposeResult(1, stdout_data, stderr_data, self) + elapsed_time = time.perf_counter() - time_start + return DockerComposeResult(1, stdout_data, stderr_data, self, elapsed_time) def _run_tutorial(self): """ @@ -374,8 +408,8 @@ def _run_tutorial(self): Returns: A DockerComposeResult object containing the state. """ - logging.debug(f"Running tutorial {self}") + time_start = time.perf_counter() stdout_data = [] stderr_data = [] try: @@ -404,11 +438,12 @@ def _run_tutorial(self): stdout_data.extend(stdout.decode().splitlines()) stderr_data.extend(stderr.decode().splitlines()) - - return DockerComposeResult(process.returncode, stdout_data, stderr_data, self) + elapsed_time = time.perf_counter() - time_start + return DockerComposeResult(process.returncode, stdout_data, stderr_data, self, elapsed_time) except Exception as e: logging.critical(f"Error executing docker compose up command: {e}") - return DockerComposeResult(1, stdout_data, stderr_data, self) + elapsed_time = time.perf_counter() - time_start + return DockerComposeResult(1, stdout_data, stderr_data, self, elapsed_time) def __repr__(self): return f"{self.tutorial.name} {self.case_combination}" @@ -419,35 +454,41 @@ def __write_logs(self, stdout_data: List[str], stderr_data: List[str]): with open(self.system_test_dir / "stderr.log", 'w') as stderr_file: stderr_file.write("\n".join(stderr_data)) - def run(self, run_directory: Path): + def __prepare_for_run(self, run_directory: Path): """ - Runs the system test by generating the Docker Compose file, copying everything into a run folder, and executing docker-compose up. + Prepares the run_directory with folders and datastructures needed for every systemtest execution """ self.__copy_tutorial_into_directory(run_directory) self.__copy_tools(run_directory) self.__put_gitignore(run_directory) - std_out: List[str] = [] - std_err: List[str] = [] uid, gid = self.__get_uid_gid() self.env["UID"] = uid self.env["GID"] = gid self.__write_env_file() + def run(self, run_directory: Path): + """ + Runs the system test by generating the Docker Compose file, copying everything into a run folder, and executing docker-compose up. + """ + self.__prepare_for_run(run_directory) + std_out: List[str] = [] + std_err: List[str] = [] + docker_build_result = self._build_docker() std_out.extend(docker_build_result.stdout_data) std_err.extend(docker_build_result.stderr_data) if docker_build_result.exit_code != 0: self.__write_logs(std_out, std_err) logging.critical(f"Could not build the docker images, {self} failed") - return SystemtestResult(False, std_out, std_err, self) + return SystemtestResult(False, std_out, std_err, self, build_time=docker_build_result.runtime, solver_time=0, fieldcompare_time=0) - docker_compose_result = self._run_tutorial() - std_out.extend(docker_compose_result.stdout_data) - std_err.extend(docker_compose_result.stderr_data) - if docker_compose_result.exit_code != 0: + docker_run_result = self._run_tutorial() + std_out.extend(docker_run_result.stdout_data) + std_err.extend(docker_run_result.stderr_data) + if docker_run_result.exit_code != 0: self.__write_logs(std_out, std_err) logging.critical(f"Could not run the tutorial, {self} failed") - return SystemtestResult(False, std_out, std_err, self) + return SystemtestResult(False, std_out, std_err, self, build_time=docker_build_result.runtime, solver_time=docker_run_result.runtime, fieldcompare_time=0) fieldcompare_result = self._run_field_compare() std_out.extend(fieldcompare_result.stdout_data) @@ -455,33 +496,55 @@ def run(self, run_directory: Path): if fieldcompare_result.exit_code != 0: self.__write_logs(std_out, std_err) logging.critical(f"Fieldcompare returned non zero exit code, therefore {self} failed") - return SystemtestResult(False, std_out, std_err, self) + return SystemtestResult(False, std_out, std_err, self, build_time=docker_build_result.runtime, solver_time=docker_run_result.runtime, fieldcompare_time=fieldcompare_result.runtime) # self.__cleanup() self.__write_logs(std_out, std_err) - return SystemtestResult(True, std_out, std_err, self) + return SystemtestResult(True, std_out, std_err, self, build_time=docker_build_result.runtime, solver_time=docker_run_result.runtime, fieldcompare_time=fieldcompare_result.runtime) def run_for_reference_results(self, run_directory: Path): """ Runs the system test by generating the Docker Compose files to generate the reference results """ - self.__copy_tutorial_into_directory(run_directory) - self.__copy_tools(run_directory) - self.__put_gitignore(run_directory) + self.__prepare_for_run(run_directory) std_out: List[str] = [] std_err: List[str] = [] - uid, gid = self.__get_uid_gid() - self.env["UID"] = uid - self.env["GID"] = gid - self.__write_env_file() - docker_compose_result = self._run_tutorial() - std_out.extend(docker_compose_result.stdout_data) - std_err.extend(docker_compose_result.stderr_data) - if docker_compose_result.exit_code == 0: - return SystemtestResult(True, std_out, std_err, self) - else: - self.__handle_docker_compose_failure(docker_compose_result) - return SystemtestResult(False, std_out, std_err, self) + docker_build_result = self._build_docker() + std_out.extend(docker_build_result.stdout_data) + std_err.extend(docker_build_result.stderr_data) + if docker_build_result.exit_code != 0: + self.__write_logs(std_out, std_err) + logging.critical(f"Could not build the docker images, {self} failed") + return SystemtestResult(False, std_out, std_err, self, build_time=docker_build_result.runtime, solver_time=0, fieldcompare_time=0) + + docker_run_result = self._run_tutorial() + std_out.extend(docker_run_result.stdout_data) + std_err.extend(docker_run_result.stderr_data) + if docker_run_result.exit_code != 0: + self.__write_logs(std_out, std_err) + logging.critical(f"Could not run the tutorial, {self} failed") + return SystemtestResult(False, std_out, std_err, self, build_time=docker_build_result.runtime, solver_time=docker_run_result.runtime, fieldcompare_time=0) + + self.__write_logs(std_out, std_err) + return SystemtestResult(True, std_out, std_err, self, build_time=docker_build_result.runtime, solver_time=docker_run_result.runtime, fieldcompare_time=0) + + def run_only_build(self, run_directory: Path): + """ + Runs only the build commmand, for example to preheat the caches of the docker builder. + """ + self.__prepare_for_run(run_directory) + std_out: List[str] = [] + std_err: List[str] = [] + docker_build_result = self._build_docker() + std_out.extend(docker_build_result.stdout_data) + std_err.extend(docker_build_result.stderr_data) + if docker_build_result.exit_code != 0: + self.__write_logs(std_out, std_err) + logging.critical(f"Could not build the docker images, {self} failed") + return SystemtestResult(False, std_out, std_err, self, build_time=docker_build_result.runtime, solver_time=0, fieldcompare_time=0) + + self.__write_logs(std_out, std_err) + return SystemtestResult(True, std_out, std_err, self, build_time=docker_build_result.runtime, solver_time=0, fieldcompare_time=0) def get_system_test_dir(self) -> Path: return self.system_test_dir From 86fe076a00672f04f6abed41df909a7fccf3a808 Mon Sep 17 00:00:00 2001 From: Valentin Seitz Date: Tue, 5 Sep 2023 00:52:16 +0200 Subject: [PATCH 17/19] added script to only build dockers to warmup cache --- tools/tests/build_docker_images.py | 96 ++++++++++++++++++++++++++++++ 1 file changed, 96 insertions(+) create mode 100644 tools/tests/build_docker_images.py diff --git a/tools/tests/build_docker_images.py b/tools/tests/build_docker_images.py new file mode 100644 index 000000000..c77b8523d --- /dev/null +++ b/tools/tests/build_docker_images.py @@ -0,0 +1,96 @@ + +import argparse +from pathlib import Path +from systemtests.SystemtestArguments import SystemtestArguments +from systemtests.Systemtest import Systemtest, display_systemtestresults_as_table +from systemtests.TestSuite import TestSuites +from metadata_parser.metdata import Tutorials +import logging +import time +from paths import PRECICE_TUTORIAL_DIR, PRECICE_TESTS_RUN_DIR, PRECICE_TESTS_DIR + + +def main(): + parser = argparse.ArgumentParser(description='build docker images') + + # Add an argument for the components + parser.add_argument('--suites', type=str, + help='Comma-separated test-suites to execute') + parser.add_argument( + '--build_args', + type=str, + help='Comma-separated list of arguments provided to the components like openfoam:2102,pythonbindings:latest') + parser.add_argument('--rundir', type=str, help='Directory to run the systemstests in.', + nargs='?', const=PRECICE_TESTS_RUN_DIR, default=PRECICE_TESTS_RUN_DIR) + + parser.add_argument('--log-level', choices=['DEBUG', 'INFO', 'WARNING', 'ERROR', 'CRITICAL'], + default='INFO', help='Set the logging level') + + # Parse the command-line arguments + args = parser.parse_args() + + # Configure logging based on the provided log level + logging.basicConfig(level=args.log_level, format='%(levelname)s: %(message)s') + + print(f"Using log-level: {args.log_level}") + + systemtests_to_run = [] + available_tutorials = Tutorials.from_path(PRECICE_TUTORIAL_DIR) + + build_args = SystemtestArguments.from_args(args.build_args) + run_directory = Path(args.rundir) + if args.suites: + test_suites_requested = args.suites.split(',') + available_testsuites = TestSuites.from_yaml( + PRECICE_TESTS_DIR / "tests.yaml", available_tutorials) + test_suites_to_execute = [] + for test_suite_requested in test_suites_requested: + test_suite_found = available_testsuites.get_by_name( + test_suite_requested) + if not test_suite_found: + logging.error(f"Did not find the testsuite with name {test_suite_requested}") + else: + test_suites_to_execute.append(test_suite_found) + if not test_suites_to_execute: + raise RuntimeError( + f"No matching test suites with names {test_suites_requested} found. Use print_test_suites.py to get an overview") + # now convert the test_suites into systemtests + for test_suite in test_suites_to_execute: + tutorials = test_suite.cases_of_tutorial.keys() + for tutorial in tutorials: + for case, reference_result in zip( + test_suite.cases_of_tutorial[tutorial], test_suite.reference_results[tutorial]): + systemtests_to_run.append( + Systemtest(tutorial, build_args, case, reference_result)) + + if not systemtests_to_run: + raise RuntimeError("Did not find any Systemtests to execute.") + + logging.info(f"About to build the images for the following systemtests:\n {systemtests_to_run}") + + results = [] + for number, systemtest in enumerate(systemtests_to_run): + logging.info(f"Started building {systemtest}, {number}/{len(systemtests_to_run)}") + t = time.perf_counter() + result = systemtest.run_only_build(run_directory) + elapsed_time = time.perf_counter() - t + logging.info(f"Building image for {systemtest} took {elapsed_time} seconds") + results.append(result) + + build_docker_success = True + for result in results: + if not result.success: + logging.error(f"Failed to run {result.systemtest}") + build_docker_success = False + else: + logging.info(f"Success running {result.systemtest}") + + display_systemtestresults_as_table(results) + if build_docker_success: + exit(0) + else: + exit(1) + + +if __name__ == '__main__': + main() From 1eb84da505b88ac3d0ba735229b8ef3e088ffab9 Mon Sep 17 00:00:00 2001 From: valentin-seitz Date: Tue, 5 Sep 2023 00:53:14 +0200 Subject: [PATCH 18/19] Update tools/tests/components.yaml Co-authored-by: Gerasimos Chourdakis --- tools/tests/components.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/tests/components.yaml b/tools/tests/components.yaml index fb35293b2..0560879e5 100644 --- a/tools/tests/components.yaml +++ b/tools/tests/components.yaml @@ -12,7 +12,7 @@ openfoam-adapter: description: Tutorial git reference to use default: "master" OPENFOAM_EXECUTABLE: - options: ["openfoam2306","openfoam2212",openfoam2112] + options: ["openfoam2306","openfoam2212","openfoam2112"] description: exectuable of openfoam to use default: "openfoam2306" OPENFOAM_ADAPTER_REF: From 2f9ac0287e15b8fdc537eb15daca9297faf9145a Mon Sep 17 00:00:00 2001 From: Valentin Seitz Date: Tue, 5 Sep 2023 00:59:10 +0200 Subject: [PATCH 19/19] make autpep8 happy --- tools/tests/systemtests/Systemtest.py | 83 +++++++++++++++++++++++---- 1 file changed, 73 insertions(+), 10 deletions(-) diff --git a/tools/tests/systemtests/Systemtest.py b/tools/tests/systemtests/Systemtest.py index 492a71a77..33056c7bc 100644 --- a/tools/tests/systemtests/Systemtest.py +++ b/tools/tests/systemtests/Systemtest.py @@ -480,7 +480,14 @@ def run(self, run_directory: Path): if docker_build_result.exit_code != 0: self.__write_logs(std_out, std_err) logging.critical(f"Could not build the docker images, {self} failed") - return SystemtestResult(False, std_out, std_err, self, build_time=docker_build_result.runtime, solver_time=0, fieldcompare_time=0) + return SystemtestResult( + False, + std_out, + std_err, + self, + build_time=docker_build_result.runtime, + solver_time=0, + fieldcompare_time=0) docker_run_result = self._run_tutorial() std_out.extend(docker_run_result.stdout_data) @@ -488,7 +495,14 @@ def run(self, run_directory: Path): if docker_run_result.exit_code != 0: self.__write_logs(std_out, std_err) logging.critical(f"Could not run the tutorial, {self} failed") - return SystemtestResult(False, std_out, std_err, self, build_time=docker_build_result.runtime, solver_time=docker_run_result.runtime, fieldcompare_time=0) + return SystemtestResult( + False, + std_out, + std_err, + self, + build_time=docker_build_result.runtime, + solver_time=docker_run_result.runtime, + fieldcompare_time=0) fieldcompare_result = self._run_field_compare() std_out.extend(fieldcompare_result.stdout_data) @@ -496,11 +510,25 @@ def run(self, run_directory: Path): if fieldcompare_result.exit_code != 0: self.__write_logs(std_out, std_err) logging.critical(f"Fieldcompare returned non zero exit code, therefore {self} failed") - return SystemtestResult(False, std_out, std_err, self, build_time=docker_build_result.runtime, solver_time=docker_run_result.runtime, fieldcompare_time=fieldcompare_result.runtime) + return SystemtestResult( + False, + std_out, + std_err, + self, + build_time=docker_build_result.runtime, + solver_time=docker_run_result.runtime, + fieldcompare_time=fieldcompare_result.runtime) # self.__cleanup() self.__write_logs(std_out, std_err) - return SystemtestResult(True, std_out, std_err, self, build_time=docker_build_result.runtime, solver_time=docker_run_result.runtime, fieldcompare_time=fieldcompare_result.runtime) + return SystemtestResult( + True, + std_out, + std_err, + self, + build_time=docker_build_result.runtime, + solver_time=docker_run_result.runtime, + fieldcompare_time=fieldcompare_result.runtime) def run_for_reference_results(self, run_directory: Path): """ @@ -515,7 +543,14 @@ def run_for_reference_results(self, run_directory: Path): if docker_build_result.exit_code != 0: self.__write_logs(std_out, std_err) logging.critical(f"Could not build the docker images, {self} failed") - return SystemtestResult(False, std_out, std_err, self, build_time=docker_build_result.runtime, solver_time=0, fieldcompare_time=0) + return SystemtestResult( + False, + std_out, + std_err, + self, + build_time=docker_build_result.runtime, + solver_time=0, + fieldcompare_time=0) docker_run_result = self._run_tutorial() std_out.extend(docker_run_result.stdout_data) @@ -523,14 +558,28 @@ def run_for_reference_results(self, run_directory: Path): if docker_run_result.exit_code != 0: self.__write_logs(std_out, std_err) logging.critical(f"Could not run the tutorial, {self} failed") - return SystemtestResult(False, std_out, std_err, self, build_time=docker_build_result.runtime, solver_time=docker_run_result.runtime, fieldcompare_time=0) + return SystemtestResult( + False, + std_out, + std_err, + self, + build_time=docker_build_result.runtime, + solver_time=docker_run_result.runtime, + fieldcompare_time=0) self.__write_logs(std_out, std_err) - return SystemtestResult(True, std_out, std_err, self, build_time=docker_build_result.runtime, solver_time=docker_run_result.runtime, fieldcompare_time=0) + return SystemtestResult( + True, + std_out, + std_err, + self, + build_time=docker_build_result.runtime, + solver_time=docker_run_result.runtime, + fieldcompare_time=0) def run_only_build(self, run_directory: Path): """ - Runs only the build commmand, for example to preheat the caches of the docker builder. + Runs only the build commmand, for example to preheat the caches of the docker builder. """ self.__prepare_for_run(run_directory) std_out: List[str] = [] @@ -541,10 +590,24 @@ def run_only_build(self, run_directory: Path): if docker_build_result.exit_code != 0: self.__write_logs(std_out, std_err) logging.critical(f"Could not build the docker images, {self} failed") - return SystemtestResult(False, std_out, std_err, self, build_time=docker_build_result.runtime, solver_time=0, fieldcompare_time=0) + return SystemtestResult( + False, + std_out, + std_err, + self, + build_time=docker_build_result.runtime, + solver_time=0, + fieldcompare_time=0) self.__write_logs(std_out, std_err) - return SystemtestResult(True, std_out, std_err, self, build_time=docker_build_result.runtime, solver_time=0, fieldcompare_time=0) + return SystemtestResult( + True, + std_out, + std_err, + self, + build_time=docker_build_result.runtime, + solver_time=0, + fieldcompare_time=0) def get_system_test_dir(self) -> Path: return self.system_test_dir