From 7b189e8610ad89054a4a7d3ffc42bd71dd9c465a Mon Sep 17 00:00:00 2001 From: Joerg Henrichs Date: Tue, 3 Dec 2024 11:39:42 +1100 Subject: [PATCH] Updated tests. --- source/fab/tools/linker.py | 3 +- tests/unit_tests/steps/test_link.py | 37 ++++++++++++++----- .../steps/test_link_shared_object.py | 22 ++++++++--- tests/unit_tests/tools/test_linker.py | 35 ++++++++++++++---- 4 files changed, 72 insertions(+), 25 deletions(-) diff --git a/source/fab/tools/linker.py b/source/fab/tools/linker.py index 9bbf0048..cb832c27 100644 --- a/source/fab/tools/linker.py +++ b/source/fab/tools/linker.py @@ -168,7 +168,6 @@ def get_pre_link_flags(self) -> List[str]: wrapped linkers ''' params: List[str] = [] - print("gplf", self._pre_lib_flags, self, self._linker) if self._pre_lib_flags: params.extend(self._pre_lib_flags) if self._linker: @@ -202,7 +201,7 @@ def link(self, input_files: List[Path], output_file: Path, linker = linker._linker # Now we must have a compiler compiler = linker._compiler - assert compiler + assert compiler # make mypy happy params.extend(compiler.flags) if openmp: diff --git a/tests/unit_tests/steps/test_link.py b/tests/unit_tests/steps/test_link.py index b6e12449..e9a6750c 100644 --- a/tests/unit_tests/steps/test_link.py +++ b/tests/unit_tests/steps/test_link.py @@ -3,22 +3,29 @@ # For further details please refer to the file COPYRIGHT # which you should have received as part of this distribution # ############################################################################## + +''' +Tests linking an executable. +''' + from pathlib import Path from types import SimpleNamespace from unittest import mock from fab.artefacts import ArtefactSet, ArtefactStore from fab.steps.link import link_exe -from fab.tools import Linker +from fab.tools import FortranCompiler, Linker import pytest class TestLinkExe: - def test_run(self, tool_box, mock_fortran_compiler): - # ensure the command is formed correctly, with the flags at the - # end (why?!) - + '''Test class for linking an executable. + ''' + def test_run(self, tool_box): + '''Ensure the command is formed correctly, with the flags at the + end and that environment variable FFLAGS is picked up. + ''' config = SimpleNamespace( project_workspace=Path('workspace'), artefact_store=ArtefactStore(), @@ -29,9 +36,20 @@ def test_run(self, tool_box, mock_fortran_compiler): config.artefact_store[ArtefactSet.OBJECT_FILES] = \ {'foo': {'foo.o', 'bar.o'}} - with mock.patch.dict("os.environ", {"FFLAGS": "-L/foo1/lib -L/foo2/lib"}): - # We need to create a linker here to pick up the env var: - linker = Linker(compiler=mock_fortran_compiler) + with mock.patch.dict("os.environ", + {"FFLAGS": "-L/foo1/lib -L/foo2/lib"}): + # We need to create the compiler here in order to pick + # up the environment + mock_compiler = FortranCompiler("mock_fortran_compiler", + "mock_fortran_compiler.exe", + "suite", module_folder_flag="", + version_regex="something", + syntax_only_flag=None, + compile_flag=None, + output_flag=None, openmp_flag=None) + mock_compiler.run = mock.Mock() + + linker = Linker(compiler=mock_compiler) # Mark the linker as available to it can be added to the tool box linker._is_available = True @@ -44,7 +62,8 @@ def test_run(self, tool_box, mock_fortran_compiler): pytest.warns(UserWarning, match="_metric_send_conn not " "set, cannot send metrics"): - link_exe(config, libs=['mylib'], flags=['-fooflag', '-barflag']) + link_exe(config, libs=['mylib'], + flags=['-fooflag', '-barflag']) tool_run.assert_called_with( ['mock_fortran_compiler.exe', '-L/foo1/lib', '-L/foo2/lib', diff --git a/tests/unit_tests/steps/test_link_shared_object.py b/tests/unit_tests/steps/test_link_shared_object.py index 5275b280..c76eb957 100644 --- a/tests/unit_tests/steps/test_link_shared_object.py +++ b/tests/unit_tests/steps/test_link_shared_object.py @@ -13,12 +13,12 @@ from fab.artefacts import ArtefactSet, ArtefactStore from fab.steps.link import link_shared_object -from fab.tools import Linker +from fab.tools import FortranCompiler, Linker import pytest -def test_run(tool_box, mock_c_compiler): +def test_run(tool_box): '''Ensure the command is formed correctly, with the flags at the end since they are typically libraries.''' @@ -33,8 +33,17 @@ def test_run(tool_box, mock_c_compiler): {None: {'foo.o', 'bar.o'}} with mock.patch.dict("os.environ", {"FFLAGS": "-L/foo1/lib -L/foo2/lib"}): - # We need to create a linker here to pick up the env var: - linker = Linker(mock_c_compiler) + # We need to create the compiler here in order to pick + # up the environment + mock_compiler = FortranCompiler("mock_fortran_compiler", + "mock_fortran_compiler.exe", + "suite", module_folder_flag="", + version_regex="something", + syntax_only_flag=None, + compile_flag=None, output_flag=None, + openmp_flag=None) + mock_compiler.run = mock.Mock() + linker = Linker(mock_compiler) # Mark the linker as available so it can added to the tool box: linker._is_available = True tool_box.add_tool(linker, silent_replace=True) @@ -47,6 +56,7 @@ def test_run(tool_box, mock_c_compiler): flags=['-fooflag', '-barflag']) tool_run.assert_called_with( - ['mock_c_compiler.exe', '-L/foo1/lib', '-L/foo2/lib', 'bar.o', 'foo.o', - '-fooflag', '-barflag', '-fPIC', '-shared', '-o', '/tmp/lib_my.so'], + ['mock_fortran_compiler.exe', '-L/foo1/lib', '-L/foo2/lib', 'bar.o', + 'foo.o', '-fooflag', '-barflag', '-fPIC', '-shared', + '-o', '/tmp/lib_my.so'], capture_output=True, env=None, cwd=None, check=False) diff --git a/tests/unit_tests/tools/test_linker.py b/tests/unit_tests/tools/test_linker.py index 0a8b1a7a..c0e31ad4 100644 --- a/tests/unit_tests/tools/test_linker.py +++ b/tests/unit_tests/tools/test_linker.py @@ -41,6 +41,31 @@ def test_linker(mock_c_compiler, mock_fortran_compiler): assert linker.flags == [] +def test_linker_constructor_error(mock_c_compiler): + '''Test the linker constructor with invalid parameters.''' + + with pytest.raises(RuntimeError) as err: + Linker() + assert ("Neither compiler nor linker is specified in linker constructor." + in str(err.value)) + with pytest.raises(RuntimeError) as err: + Linker(compiler=mock_c_compiler, linker=mock_c_compiler) + assert ("Both compiler and linker is specified in linker constructor." + in str(err.value)) + + +@pytest.mark.parametrize("mpi", [True, False]) +def test_linker_mpi(mock_c_compiler, mpi): + '''Test the linker constructor with invalid parameters.''' + + mock_c_compiler._mpi = mpi + linker = Linker(compiler=mock_c_compiler) + assert linker.mpi == mpi + + wrapped_linker = Linker(linker=linker) + assert wrapped_linker.mpi == mpi + + def test_linker_gets_ldflags(mock_c_compiler): """Tests that the linker retrieves env.LDFLAGS""" with mock.patch.dict("os.environ", {"LDFLAGS": "-lm"}): @@ -250,14 +275,8 @@ def test_linker_all_flag_types(mock_c_compiler): """Make sure all possible sources of linker flags are used in the right order""" - # Environment variables for both the compiler and linker - # TODO: THIS IS ACTUALLY WRONG - The FFLAGS shouldn't be picked up here, - # because the compiler already exists. It is being added twice, because - # Linker inherits Compiler (in addition to wrapping it) - with mock.patch.dict("os.environ", { - "FFLAGS": "-fflag", - "LDFLAGS": "-ldflag" - }): + # Environment variables for both the linker + with mock.patch.dict("os.environ", {"LDFLAGS": "-ldflag"}): linker = Linker(compiler=mock_c_compiler) mock_c_compiler.add_flags(["-compiler-flag1", "-compiler-flag2"])