Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions score/mw/com/impl/methods/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,17 @@ cc_library(
],
)

cc_library(
name = "method_handler_checker",
srcs = ["method_handler_checker.cpp"],
hdrs = ["method_handler_checker.h"],
features = COMPILER_WARNING_FEATURES,
tags = ["FFI"],
visibility = [
"//score/mw/com:__subpackages__",
],
)

cc_library(
name = "proxy_method_base",
srcs = ["proxy_method_base.cpp"],
Expand Down Expand Up @@ -186,6 +197,7 @@ cc_gtest_unit_test(
":skeleton_method",
"//score/mw/com/impl/bindings/mock_binding",
"//score/mw/com/impl/plumbing:skeleton_method_binding_factory_mock",
"//score/mw/com/impl/test:binding_factory_resources",
"@score_baselibs//score/language/futurecpp",
],
)
Expand Down
19 changes: 19 additions & 0 deletions score/mw/com/impl/methods/compile_tests/BUILD
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
load(":compile_fail.bzl", "compile_fail_test")
load("@score_baselibs//:bazel/unit_tests.bzl", "cc_unit_test_suites_for_host_and_qnx")

compile_fail_test(
name = "method_handler_checker_compile_fail_test",
src = "method_handler_checker_test.cpp",
src_path = "score/mw/com/impl/methods/compile_tests/method_handler_checker_test.cpp",
deps = [
"//score/mw/com/impl/methods:method_handler_checker",
],
)

cc_unit_test_suites_for_host_and_qnx(
name = "unit_test_suite",
cc_unit_tests = [
":method_handler_checker_compile_fail_test",
],
visibility = ["//score/mw/com/impl/methods:__pkg__"],
)
158 changes: 158 additions & 0 deletions score/mw/com/impl/methods/compile_tests/compile_fail.bzl
Original file line number Diff line number Diff line change
@@ -0,0 +1,158 @@
"""Rule for compile-fail tests: a test passes if and only if its source file fails to compile."""

load("@bazel_tools//tools/cpp:toolchain_utils.bzl", "find_cpp_toolchain", "use_cpp_toolchain")

# Stable action-name string; avoids a dep on @rules_cc//cc:action_names.bzl.
_CPP_COMPILE_ACTION = "c++-compile"

def _compile_fail_test_impl(ctx):
cc_toolchain = find_cpp_toolchain(ctx)
feature_configuration = cc_common.configure_features(
ctx = ctx,
cc_toolchain = cc_toolchain,
requested_features = ctx.features,
unsupported_features = ctx.disabled_features,
)

compiler = cc_common.get_tool_for_action(
feature_configuration = feature_configuration,
action_name = _CPP_COMPILE_ACTION,
)

compilation_contexts = [
dep[CcInfo].compilation_context
for dep in ctx.attr.deps
if CcInfo in dep
]
merged = cc_common.merge_compilation_contexts(
compilation_contexts = compilation_contexts,
)

# Include paths from the compilation context are exec-root-relative.
# At test time, we resolve them against runfiles.
flag_lines = ["flags=()"]
for path in merged.includes.to_list():
flag_lines.append('flags+=( -I"$(resolve_data_path \"{p}\")" )'.format(p = path))
for path in merged.quote_includes.to_list():
flag_lines.append('flags+=( -iquote "$(resolve_data_path \"{p}\")" )'.format(p = path))
for path in merged.system_includes.to_list():
flag_lines.append('flags+=( -isystem "$(resolve_data_path \"{p}\")" )'.format(p = path))
for define in merged.defines.to_list():
flag_lines.append('flags+=( -D"{d}" )'.format(d = define))
for copt in ctx.attr.copts:
flag_lines.append("flags+=( {c} )".format(c = copt))

# Add generic include roots for workspace headers.
flag_lines.append('flags+=( -iquote "$(resolve_data_path .)" )')
flag_lines.append('flags+=( -iquote "$TEST_SRCDIR/$TEST_WORKSPACE" )')

# The test script inverts the compiler exit code:
# compile succeeds → test fails
# compile fails → test passes
test_script = ctx.actions.declare_file(ctx.label.name)
ctx.actions.write(
output = test_script,
content = """\
#!/usr/bin/env bash
set -uo pipefail

resolve_data_path() {{
local p="$1"
if [[ -e "$TEST_SRCDIR/$p" ]]; then
echo "$TEST_SRCDIR/$p"
return 0
fi
if [[ -n "${{TEST_WORKSPACE:-}}" && -e "$TEST_SRCDIR/$TEST_WORKSPACE/$p" ]]; then
echo "$TEST_SRCDIR/$TEST_WORKSPACE/$p"
return 0
fi
echo "$TEST_SRCDIR/$p"
return 0
}}

resolve_exec_path() {{
local p="$1"
if [[ -x "$p" ]]; then
echo "$p"
return 0
fi
if [[ -x "$TEST_SRCDIR/$p" ]]; then
echo "$TEST_SRCDIR/$p"
return 0
fi
if [[ -n "${{TEST_WORKSPACE:-}}" && -x "$TEST_SRCDIR/$TEST_WORKSPACE/$p" ]]; then
echo "$TEST_SRCDIR/$TEST_WORKSPACE/$p"
return 0
fi
return 1
}}

src="$(resolve_data_path \"{src}\")"
compiler=""
if compiler_candidate="$(resolve_exec_path \"{compiler}\")"; then
compiler="$compiler_candidate"
else
compiler="$(command -v c++ || command -v g++)"
fi

if [[ -z "$compiler" ]]; then
echo "FAILED: compiler '{compiler}' not found/executable in runfiles and no c++/g++ in PATH."
exit 2
fi

if [[ ! -f "$src" ]]; then
echo "FAILED: source '{src}' not found in runfiles."
exit 2
fi

{flag_lines}
if "$compiler" "${{flags[@]}}" -c "$src" -o /dev/null 2>/dev/null; then
echo "FAILED: expected a compile error, but '{src}' compiled successfully."
exit 1
fi
echo "PASSED: '{src}' failed to compile as expected."
exit 0
""".format(
src = ctx.attr.src_path,
compiler = compiler,
flag_lines = "\n".join(flag_lines),
),
is_executable = True,
)

runfiles = ctx.runfiles(
files = [ctx.file.src],
transitive_files = depset(transitive = [
cc_toolchain.all_files,
merged.headers,
]),
)
return [DefaultInfo(executable = test_script, runfiles = runfiles)]

compile_fail_test = rule(
implementation = _compile_fail_test_impl,
attrs = {
"src": attr.label(
mandatory = True,
allow_single_file = [".cpp", ".cc", ".cxx"],
doc = "The C++ source file expected to fail compilation.",
),
"src_path": attr.string(
mandatory = True,
doc = "Runfiles-relative path of the source file to compile.",
),
"deps": attr.label_list(
providers = [CcInfo],
doc = "C++ library dependencies.",
),
"copts": attr.string_list(
doc = "Additional compiler flags.",
),
"_cc_toolchain": attr.label(
default = Label("@bazel_tools//tools/cpp:current_cc_toolchain"),
),
},
test = True,
fragments = ["cpp"],
toolchains = use_cpp_toolchain(),
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
#include "score/mw/com/impl/methods/method_handler_checker.h"

#include <functional>

int main()
{
score::mw::com::impl::
AssertCallableMatchesMethodSignature<std::function<void(int&, const int&, const double&)>, int, int, double>();
return 0;
}
13 changes: 13 additions & 0 deletions score/mw/com/impl/methods/method_handler_checker.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
/********************************************************************************
* Copyright (c) 2025 Contributors to the Eclipse Foundation
*
* See the NOTICE file(s) distributed with this work for additional
* information regarding copyright ownership.
*
* This program and the accompanying materials are made available under the
* terms of the Apache License Version 2.0 which is available at
* https://www.apache.org/licenses/LICENSE-2.0
*
* SPDX-License-Identifier: Apache-2.0
********************************************************************************/
#include "score/mw/com/impl/methods/method_handler_checker.h"
Loading
Loading