blob: 1118342b632e0ec26899dbf3587264512da7274b [file] [log] [blame]
"""Copyright (C) 2022 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
"""
load("@bazel_skylib//lib:unittest.bzl", "analysistest", "asserts")
load(
":cc_toolchain_constants.bzl",
"generated_config_constants",
"generated_sanitizer_constants",
)
load(
"//build/bazel/rules/test_common:flags.bzl",
"action_flags_absent_for_mnemonic_test",
"action_flags_present_for_mnemonic_nonexclusive_test",
"action_flags_present_only_for_mnemonic_test",
)
compile_action_mnemonic = "CppCompile"
link_action_mnemonic = "CppLink"
def test_cfi_c_and_cpp_has_correct_flags():
name = "cfi_c_and_cpp_has_correct_flags"
native.cc_binary(
name = name,
srcs = ["foo.c", "bar.cpp"],
features = ["android_cfi"],
tags = ["manual"],
)
compile_test_name = name + "_compile_test"
action_flags_present_for_mnemonic_nonexclusive_test(
name = compile_test_name,
target_under_test = name,
mnemonics = [compile_action_mnemonic],
expected_flags = generated_sanitizer_constants.CfiCFlags +
[generated_sanitizer_constants.CfiCrossDsoFlag],
)
link_test_name = name + "_link_test"
action_flags_present_for_mnemonic_nonexclusive_test(
name = link_test_name,
target_under_test = name,
mnemonics = [link_action_mnemonic],
expected_flags = generated_sanitizer_constants.CfiLdFlags +
[generated_sanitizer_constants.CfiCrossDsoFlag],
)
return [
compile_test_name,
link_test_name,
]
def test_cfi_s_has_correct_flags():
name = "cfi_s_has_correct_flags"
native.cc_binary(
name = name,
srcs = ["baz.s", "blah.S"],
features = ["android_cfi"],
tags = ["manual"],
)
assemble_test_name = name + "_assemble_test"
action_flags_present_only_for_mnemonic_test(
name = assemble_test_name,
target_under_test = name,
mnemonics = [compile_action_mnemonic],
expected_flags = generated_sanitizer_constants.CfiAsFlags,
)
compile_flags_absent_test_name = name + "_compile_flags_absent_test"
action_flags_absent_for_mnemonic_test(
name = compile_flags_absent_test_name,
target_under_test = name,
mnemonics = [compile_action_mnemonic],
expected_absent_flags = generated_sanitizer_constants.CfiCFlags +
[generated_sanitizer_constants.CfiCrossDsoFlag],
)
return [
assemble_test_name,
compile_flags_absent_test_name,
]
def test_cross_dso_not_added_when_cfi_disabled():
name = "cross_dso_not_added_when_cfi_disabled"
native.cc_binary(
name = name,
srcs = ["foo.c", "bar.cpp"],
features = ["android_cfi_cross_dso"],
tags = ["manual"],
)
test_name = name + "_test"
action_flags_absent_for_mnemonic_test(
name = test_name,
target_under_test = name,
mnemonics = [compile_action_mnemonic, link_action_mnemonic],
expected_absent_flags = [generated_sanitizer_constants.CfiCrossDsoFlag],
)
return test_name
def test_cross_dso_not_added_when_static_binary():
name = "cross_dso_not_added_when_static_binary"
native.cc_binary(
name = name,
srcs = ["foo.c", "bar.cpp"],
features = [
"android_cfi",
"static_executable",
"-dynamic_executable",
"android_cfi_cross_dso",
],
tags = ["manual"],
)
android_test_name = name + "_android_test"
action_flags_absent_for_mnemonic_test(
name = android_test_name,
target_under_test = name,
mnemonics = [compile_action_mnemonic, link_action_mnemonic],
expected_absent_flags = [generated_sanitizer_constants.CfiCrossDsoFlag],
target_compatible_with = ["//build/bazel/platforms/os:android"],
)
linux_test_name = name + "_linux_test"
action_flags_absent_for_mnemonic_test(
name = linux_test_name,
target_under_test = name,
mnemonics = [compile_action_mnemonic, link_action_mnemonic],
expected_absent_flags = [generated_sanitizer_constants.CfiCrossDsoFlag],
target_compatible_with = ["//build/bazel/platforms/os:linux_glibc"],
)
return [
android_test_name,
linux_test_name,
]
def test_cfi_assembly_support_has_correct_flags():
name = "cfi_assembly_support_has_correct_flags"
native.cc_binary(
name = name,
srcs = ["foo.c", "bar.cpp"],
features = [
"android_cfi",
"android_cfi_assembly_support",
],
tags = ["manual"],
)
test_name = name + "_test"
action_flags_present_only_for_mnemonic_test(
name = test_name,
target_under_test = name,
mnemonics = [compile_action_mnemonic],
expected_flags = [generated_sanitizer_constants.CfiAssemblySupportFlag],
)
return test_name
def test_cfi_assembly_support_does_not_add_flags_for_s():
name = "cfi_assembly_support_does_not_add_flags_for_s"
native.cc_binary(
name = name,
srcs = ["baz.s", "blah.S"],
features = [
"android_cfi",
"android_cfi_assembly_support",
],
tags = ["manual"],
)
test_name = name + "_test"
action_flags_absent_for_mnemonic_test(
name = test_name,
target_under_test = name,
mnemonics = [compile_action_mnemonic],
expected_absent_flags = [
generated_sanitizer_constants.CfiAssemblySupportFlag,
],
)
return test_name
def test_cfi_exports_map_has_correct_flags():
name = "cfi_exports_map_has_correct_flags"
native.cc_binary(
name = name,
srcs = ["foo.c", "bar.cpp"],
features = [
"android_cfi",
"android_cfi_exports_map",
],
tags = ["manual"],
)
test_name = name + "_test"
action_flags_present_only_for_mnemonic_test(
name = test_name,
target_under_test = name,
mnemonics = [link_action_mnemonic],
expected_flags = [
generated_config_constants.VersionScriptFlagPrefix +
generated_sanitizer_constants.CfiExportsMapPath +
"/" +
generated_sanitizer_constants.CfiExportsMapFilename,
],
)
return test_name
def test_cfi_cross_dso_has_correct_flags():
name = "cfi_cross_dso_has_correct_flags"
native.cc_binary(
name = name,
srcs = ["foo.c", "bar.cpp"],
features = [
"android_cfi",
"android_cfi_cross_dso",
],
tags = ["manual"],
)
test_name = name + "_test"
action_flags_present_only_for_mnemonic_test(
name = test_name,
target_under_test = name,
mnemonics = [compile_action_mnemonic, link_action_mnemonic],
expected_flags = [generated_sanitizer_constants.CfiCrossDsoFlag],
)
return test_name
def test_cfi_cross_dso_does_not_add_flags_for_s():
name = "cfi_cross_dso_does_not_add_flags_for_s"
native.cc_binary(
name = name,
srcs = ["baz.s", "blah.S"],
features = [
"android_cfi",
"android_cfi_cross_dso",
],
tags = ["manual"],
)
test_name = name + "_test"
action_flags_absent_for_mnemonic_test(
name = test_name,
target_under_test = name,
mnemonics = [compile_action_mnemonic],
expected_absent_flags = [generated_sanitizer_constants.CfiCrossDsoFlag],
)
return test_name
def test_cfi_implies_lto():
name = "cfi_implies_lto"
native.cc_binary(
name = name,
srcs = ["foo.c", "bar.cpp"],
features = ["android_cfi"],
tags = ["manual"],
)
test_name = name + "_test"
action_flags_present_for_mnemonic_nonexclusive_test(
name = test_name,
target_under_test = name,
mnemonics = [compile_action_mnemonic],
expected_flags = ["-flto=thin"],
)
return test_name
def test_cfi_implies_vis_default_if_not_hidden():
name = "cfi_implies_vis_default_if_not_hidden"
native.cc_binary(
name = name,
srcs = ["foo.c", "bar.cpp"],
features = ["android_cfi"],
tags = ["manual"],
)
test_name = name + "_test"
action_flags_present_only_for_mnemonic_test(
name = test_name,
target_under_test = name,
mnemonics = [compile_action_mnemonic],
expected_flags = ["-fvisibility=default"],
)
return test_name
def test_cfi_does_not_add_vis_default_if_hidden():
name = "cfi_does_not_add_vis_default_if_hidden"
native.cc_binary(
name = name,
srcs = ["foo.c", "bar.cpp"],
features = ["android_cfi", "visibility_hidden"],
tags = ["manual"],
)
test_name = name + "_test"
action_flags_absent_for_mnemonic_test(
name = test_name,
target_under_test = name,
mnemonics = [compile_action_mnemonic],
expected_absent_flags = ["-fvisibility=default"],
)
return test_name
def test_cfi_and_arm_uses_thumb():
name = "cfi_and_arm_uses_thumb"
native.cc_binary(
name = name,
srcs = ["foo.c", "bar.cpp"],
features = ["android_cfi"],
tags = ["manual"],
)
test_name = name + "_test"
action_flags_present_for_mnemonic_nonexclusive_test(
name = test_name,
target_under_test = name,
mnemonics = [compile_action_mnemonic],
expected_flags = generated_config_constants.ArmThumbCflags,
target_compatible_with = [
"//build/bazel/platforms/arch:arm",
],
)
return test_name
# TODO(b/274924237): Uncomment after Darwin and Windows have toolchains
#def test_cfi_absent_on_unsupported_oses():
# name = "cfi_absent_on_unsupported_oses"
# native.cc_binary(
# name = name,
# srcs = ["foo.c", "bar.cpp"],
# features = ["android_cfi"],
# tags = ["manual"],
# )
#
# test_name = name + "_test"
# action_flags_absent_for_mnemonic_test(
# name = test_name,
# target_under_test = name,
# mnemonics = [compile_action_mnemonic],
# expected_absent_flags = generated_sanitizer_constants.CfiCFlags,
# target_compatible_with = [
# "//build/bazel/platforms/os:linux_musl",
# "//build/bazel/platforms/os:darwin",
# "//build/bazel/platforms/os:windows",
# ]
# )
#
# return test_name
def cc_toolchain_features_cfi_test_suite(name):
individual_tests = [
test_cross_dso_not_added_when_cfi_disabled(),
test_cfi_assembly_support_has_correct_flags(),
test_cfi_assembly_support_does_not_add_flags_for_s(),
test_cfi_exports_map_has_correct_flags(),
test_cfi_cross_dso_has_correct_flags(),
test_cfi_cross_dso_does_not_add_flags_for_s(),
test_cfi_implies_lto(),
test_cfi_implies_vis_default_if_not_hidden(),
test_cfi_does_not_add_vis_default_if_hidden(),
test_cfi_and_arm_uses_thumb(),
# TODO(b/274924237): Uncomment after Darwin and Windows have toolchains
# test_cfi_absent_on_unsupported_oses(),
]
native.test_suite(
name = name,
tests = individual_tests +
test_cfi_c_and_cpp_has_correct_flags() +
test_cfi_s_has_correct_flags() +
test_cross_dso_not_added_when_static_binary(),
)