Skip to content
Snippets Groups Projects
Code owners
Assign users and groups as approvers for specific file changes. Learn more.
test_make_build.py 4.68 KiB
import os
import sys
import re

import pytest

from ..utils import RE_MISSING_FILE, RE_MISSING_VERSION


def test_error_if_missing_source_file(wrapper):
    wrapper.write_var_to_makefile(
        wrapper.module_makefile, "SOURCES", "nonexistent.c", modifier="+"
    )

    rc, _, errs = wrapper.run_make("build")
    assert rc == 2
    assert re.search(
        RE_MISSING_FILE.format(filename=re.escape("nonexistent.o")),
        errs,
    )


def test_error_if_missing_dbd_file(wrapper):
    wrapper.write_var_to_makefile(
        wrapper.module_makefile, "DBDS", "nonexistent.dbd", modifier="+"
    )

    rc, _, errs = wrapper.run_make("build")
    assert rc == 2
    assert re.search(
        RE_MISSING_FILE.format(filename=re.escape("../nonexistent.dbd")),
        errs,
    )


@pytest.mark.skipif(sys.platform == "darwin", reason="this fails on the regex search")
def test_error_if_missing_record_dbd_file(wrapper):
    wrapper.add_file("fooRecord.c")
    wrapper.write_var_to_makefile(
        wrapper.module_makefile, "SOURCES", "fooRecord.c", modifier="+"
    )

    rc, _, errs = wrapper.run_make("build")
    assert rc != 0
    assert re.search(
        RE_MISSING_FILE.format(
            filename=re.escape(f"../O.{wrapper.base_version}_Common/fooRecord.dbd")
        ),
        errs,
    )


def test_error_if_missing_requirement(wrapper):
    missing_module = "FOO"
    wrapper.write_var_to_makefile(
        wrapper.config_module,
        f"{missing_module}_DEP_VERSION",
        "bar",
        export=True,
    )

    rc, _, errs = wrapper.run_make("build")
    assert rc != 0
    assert (
        f'Dependent module "{missing_module.lower()}" (from "{missing_module}_DEP_VERSION") not installed'
        in errs
    )


def test_error_if_missing_pinned_requirement(wrapper_factory):
    wrapper_dep = wrapper_factory.create()
    wrapper_main = wrapper_factory.create()

    cell_path = wrapper_main.wrapper_dir / "cellMods"

    _ = wrapper_dep.run_make("cellinstall", cell_path=cell_path)

    missing_version = "not_a_real_version"
    wrapper_main.write_var_to_makefile(
        wrapper_main.config_module,
        f"{wrapper_dep.name}_DEP_VERSION",
        missing_version,
        export=True,
    )

    rc, _, errs = wrapper_main.run_make("cellbuild")
    assert rc == 2
    assert re.search(
        RE_MISSING_VERSION.format(module=wrapper_dep.name, version=missing_version),
        errs,
    )


@pytest.mark.skipif(
    sys.platform == "darwin", reason="this fails at update for reasons beyond me"
)
def test_updated_template_files(wrapper):
    wrapper.write_var_to_makefile(
        wrapper.module_makefile, "SUBS", "x.substitutions", modifier="+"
    )
    wrapper.write_var_to_makefile(
        wrapper.module_makefile, "USR_DBFLAGS", "-I.", modifier="+"
    )

    substitution_file = wrapper.module_dir / "x.substitutions"
    substitution_file.write_text("file x.template {pattern {x} {y}}")

    template_file = wrapper.module_dir / "x.template"
    template_file.write_text("record(ai, initial) {}")

    db_file = wrapper.module_dir / f"O.{wrapper.base_version}_Common" / "x.db"

    rc, *_ = wrapper.run_make("db_internal")
    assert rc == 0
    assert db_file.read_text() == "record(ai, initial) {}"

    template_file.write_text("record(ai, updated) {}")

    rc, *_ = wrapper.run_make("db_internal")
    assert rc == 0
    assert db_file.read_text() == "record(ai, updated) {}"


@pytest.mark.skipif(sys.platform != "linux", reason="only works for linux")
@pytest.mark.parametrize("archs,failing_arch", [("foo bar", "foo"), ("foo bar", "bar")])
def test_build_fails_if_nth_architecture_fails(wrapper, archs, failing_arch):
    # LIBOBJS is determined in part based on configuration data coming from
    # $(CONFIG)/os/CONFIG.Common.$(T_A); since our architectures do not actually
    # exist, we need to manually define these /before/ driver.makefile is included.
    makefile_content = wrapper.module_makefile.read_text()
    new_content = (
        f"""\
ifeq ($(T_A),{failing_arch})
LIBOBJS = nonexistent_{failing_arch}.o
endif
"""
        + makefile_content
    )
    wrapper.module_makefile.write_text(new_content)

    wrapper.write_var_to_makefile(
        wrapper.config_module, "OS_CLASS", "Linux", export=True
    )

    # Skip the host architecture, we are not testing it.
    host_arch = os.environ["EPICS_HOST_ARCH"]
    wrapper.write_var_to_makefile(
        wrapper.module_makefile, "EXCLUDE_ARCHS", host_arch, modifier="+"
    )

    wrapper.write_var_to_makefile(
        wrapper.module_makefile, "CROSS_COMPILER_TARGET_ARCHS", archs
    )

    rc, _, errs = wrapper.run_make("build")
    assert rc == 2
    assert re.search(
        RE_MISSING_FILE.format(filename=re.escape(f"nonexistent_{failing_arch}.o")),
        errs,
    )