Skip to content

Commit

Permalink
Fix up tests for new Linker inheritence
Browse files Browse the repository at this point in the history
  • Loading branch information
Luke Hoffmann committed Sep 25, 2024
1 parent 205226a commit 1f957f2
Show file tree
Hide file tree
Showing 7 changed files with 26 additions and 40 deletions.
2 changes: 1 addition & 1 deletion source/fab/tools/compiler.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ def __init__(self, name: str,
self._compile_flag = compile_flag if compile_flag else "-c"
self._output_flag = output_flag if output_flag else "-o"
self._openmp_flag = openmp_flag if openmp_flag else ""
self.flags.extend(os.getenv("FFLAGS", "").split())
self.add_flags(os.getenv("FFLAGS", "").split())

@property
def mpi(self) -> bool:
Expand Down
2 changes: 1 addition & 1 deletion source/fab/tools/linker.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ def __init__(self, compiler: Compiler, output_flag: str = "-o"):
category=Category.LINKER,
mpi=compiler.mpi)

self._flags.extend(os.getenv("LDFLAGS", "").split())
self.add_flags(os.getenv("LDFLAGS", "").split())

# Maintain a set of flags for common libraries.
self._lib_flags: Dict[str, List[str]] = {}
Expand Down
2 changes: 1 addition & 1 deletion source/fab/tools/preprocessor.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ class CppFortran(Preprocessor):
'''
def __init__(self):
super().__init__("cpp", "cpp", Category.FORTRAN_PREPROCESSOR)
self.flags.extend(["-traditional-cpp", "-P"])
self.add_flags(["-traditional-cpp", "-P"])


# ============================================================================
Expand Down
5 changes: 2 additions & 3 deletions tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,10 +42,9 @@ def fixture_mock_fortran_compiler():


@pytest.fixture(name="mock_linker")
def fixture_mock_linker():
def fixture_mock_linker(mock_fortran_compiler):
'''Provides a mock linker.'''
mock_linker = Linker("mock_linker", "mock_linker.exe",
Category.FORTRAN_COMPILER)
mock_linker = Linker(mock_fortran_compiler)
mock_linker.run = mock.Mock()
mock_linker._version = (1, 2, 3)
mock_linker.add_lib_flags("netcdf", ["-lnetcdff", "-lnetcdf"])
Expand Down
9 changes: 5 additions & 4 deletions tests/unit_tests/steps/test_link.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@


class TestLinkExe:
def test_run(self, tool_box):
def test_run(self, tool_box, mock_fortran_compiler):
# ensure the command is formed correctly, with the flags at the
# end (why?!)

Expand All @@ -29,9 +29,9 @@ def test_run(self, tool_box):
config.artefact_store[ArtefactSet.OBJECT_FILES] = \
{'foo': {'foo.o', 'bar.o'}}

with mock.patch('os.getenv', return_value='-L/foo1/lib -L/foo2/lib'):
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_link", "mock_link.exe", "mock-vendor")
linker = Linker(mock_fortran_compiler)
# Mark the linker as available to it can be added to the tool box
linker._is_available = True

Expand All @@ -47,7 +47,8 @@ def test_run(self, tool_box):
link_exe(config, libs=['mylib'], flags=['-fooflag', '-barflag'])

tool_run.assert_called_with(
['mock_link.exe', '-L/foo1/lib', '-L/foo2/lib', 'bar.o', 'foo.o',
['mock_fortran_compiler.exe', '-L/foo1/lib', '-L/foo2/lib',
'bar.o', 'foo.o',
'-L/my/lib', '-mylib', '-fooflag', '-barflag',
'-o', 'workspace/foo'],
capture_output=True, env=None, cwd=None, check=False)
8 changes: 4 additions & 4 deletions tests/unit_tests/steps/test_link_shared_object.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
import pytest


def test_run(tool_box):
def test_run(tool_box, mock_c_compiler):
'''Ensure the command is formed correctly, with the flags at the
end since they are typically libraries.'''

Expand All @@ -32,9 +32,9 @@ def test_run(tool_box):
config.artefact_store[ArtefactSet.OBJECT_FILES] = \
{None: {'foo.o', 'bar.o'}}

with mock.patch('os.getenv', return_value='-L/foo1/lib -L/foo2/lib'):
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_link", "mock_link.exe", "vendor")
linker = Linker(mock_c_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)
Expand All @@ -47,6 +47,6 @@ def test_run(tool_box):
flags=['-fooflag', '-barflag'])

tool_run.assert_called_with(
['mock_link.exe', '-L/foo1/lib', '-L/foo2/lib', 'bar.o', 'foo.o',
['mock_c_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)
38 changes: 12 additions & 26 deletions tests/unit_tests/tools/test_linker.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,11 +39,6 @@ def test_linker(mock_c_compiler, mock_fortran_compiler):
assert linker.suite == "suite"
assert linker.flags == []

with pytest.raises(RuntimeError) as err:
linker = Linker(name="no-exec-given")
assert ("Either specify name, exec name, and suite or a compiler when "
"creating Linker." in str(err.value))


def test_linker_gets_ldflags(mock_c_compiler):
"""Tests that the linker retrieves env.LDFLAGS"""
Expand Down Expand Up @@ -247,29 +242,22 @@ def test_compiler_linker_add_compiler_flag(mock_c_compiler):
capture_output=True, env=None, cwd=None, check=False)


def test_linker_add_compiler_flag():
'''Make sure ad-hoc linker flags work if a linker is created without a
compiler:
'''
linker = Linker("no-compiler", "no-compiler.exe", "suite")
linker.flags.append("-some-other-flag")
mock_result = mock.Mock(returncode=0)
with mock.patch('fab.tools.tool.subprocess.run',
return_value=mock_result) as tool_run:
linker.link([Path("a.o")], Path("a.out"), openmp=False)
tool_run.assert_called_with(
['no-compiler.exe', '-some-other-flag', 'a.o', '-o', 'a.out'],
capture_output=True, env=None, cwd=None, check=False)


def test_linker_all_flag_types(mock_c_compiler):
"""Make sure all possible sources of linker flags are used in the right
order"""
with mock.patch.dict("os.environ", {"LDFLAGS": "-ldflag"}):

# 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"
}):
linker = Linker(compiler=mock_c_compiler)

mock_c_compiler.flags.extend(["-compiler-flag1", "-compiler-flag2"])
linker.flags.extend(["-linker-flag1", "-linker-flag2"])
mock_c_compiler.add_flags(["-compiler-flag1", "-compiler-flag2"])
linker.add_flags(["-linker-flag1", "-linker-flag2"])
linker.add_pre_lib_flags(["-prelibflag1", "-prelibflag2"])
linker.add_lib_flags("customlib1", ["-lib1flag1", "lib1flag2"])
linker.add_lib_flags("customlib2", ["-lib2flag1", "lib2flag2"])
Expand All @@ -285,10 +273,8 @@ def test_linker_all_flag_types(mock_c_compiler):

tool_run.assert_called_with([
"mock_c_compiler.exe",
# Note: compiler flags and linker flags will be switched when the Linker
# becomes a CompilerWrapper in a following PR
"-compiler-flag1", "-compiler-flag2", "-fflag",
"-ldflag", "-linker-flag1", "-linker-flag2",
"-compiler-flag1", "-compiler-flag2",
"-fopenmp",
"a.o",
"-prelibflag1", "-prelibflag2",
Expand Down

0 comments on commit 1f957f2

Please sign in to comment.