Skip to content

Commit

Permalink
pw_compilation_testing: Add negative compilation tests
Browse files Browse the repository at this point in the history
- Convert existing negative compilation tests to the new framework.
- Add a negative compilation test for pw_rpc service creation.

Change-Id: I204f4602dd8f49cb7c59fda04fbb1321828640ae
Reviewed-on: https://pigweed-review.googlesource.com/c/pigweed/pigweed/+/103364
Commit-Queue: Wyatt Hepler <[email protected]>
Reviewed-by: Keir Mierle <[email protected]>
Pigweed-Auto-Submit: Wyatt Hepler <[email protected]>
  • Loading branch information
255 authored and CQ Bot Account committed Aug 5, 2022
1 parent 77497ce commit 1b7adca
Show file tree
Hide file tree
Showing 21 changed files with 116 additions and 26 deletions.
1 change: 1 addition & 0 deletions pw_assert/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@ pw_cc_test(
deps = [
":facade",
"//pw_assert",
"//pw_compilation_testing:negative_compilation_testing",
"//pw_preprocessor",
"//pw_span",
"//pw_string",
Expand Down
1 change: 1 addition & 0 deletions pw_assert/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,7 @@ pw_test("assert_facade_test") {
dir_pw_status,
dir_pw_string,
]
negative_compilation_tests = true

# TODO(frolv): Fix this test on the QEMU target.
enable_if = pw_build_EXECUTABLE_TARGET_TYPE != "lm3s6965evb_executable"
Expand Down
1 change: 1 addition & 0 deletions pw_assert/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,7 @@ pw_add_test(pw_assert.assert_facade_test
pw_assert_test/fake_backend.h
DEPS
pw_assert
pw_compilation_testing._pigweed_only_negative_compilation
pw_status
pw_string
GROUPS
Expand Down
9 changes: 9 additions & 0 deletions pw_assert/assert_facade_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
// clang-format on

#include "gtest/gtest.h"
#include "pw_compilation_testing/negative_compilation.h"
#include "pw_status/status.h"

namespace {
Expand Down Expand Up @@ -282,6 +283,14 @@ TEST_F(AssertFailTest, FunctionPtrNotNull) {
PW_CHECK_NOTNULL(function);
}

[[maybe_unused]] void CompareIntWithString() {
#if PW_NC_TEST(CompareIntWithString)
PW_NC_EXPECT("cannot initialize|invalid conversion");

PW_CHECK_INT_EQ(123l, "This check message is accidentally compared to 123!");
#endif // PW_NC_TEST
}

// Note: Due to platform inconsistencies, the below test for the NOTNULL
// message doesn't work. Some platforms print NULL formatted as %p as "(nil)",
// others "0x0". Leaving this here for reference.
Expand Down
4 changes: 3 additions & 1 deletion pw_compilation_testing/docs.rst
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,9 @@ scenarios, for example:
- For a ``constexpr`` function, testing that a ``PW_ASSERT`` is triggered as
expected.

Negative compilation tests are only supported in GN currently.
Negative compilation tests are only supported in GN currently. Negative
compilation tests are not currently supported in GN on Windows due to
`b/241565082 <bugs.pigweed.dev/241565082>`_.

.. warning::

Expand Down
5 changes: 4 additions & 1 deletion pw_containers/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,10 @@ pw_cc_library(
"public/pw_containers/intrusive_list.h",
],
includes = ["public"],
deps = ["//pw_assert"],
deps = [
"//pw_assert",
"//pw_compilation_testing:negative_compilation_testing",
],
)

pw_cc_library(
Expand Down
1 change: 1 addition & 0 deletions pw_containers/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,7 @@ pw_test("intrusive_list_test") {
":intrusive_list",
"$dir_pw_preprocessor",
]
negative_compilation_tests = true
}

pw_doc_group("docs") {
Expand Down
1 change: 1 addition & 0 deletions pw_containers/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,7 @@ pw_add_test(pw_containers.intrusive_list_test
SOURCES
intrusive_list_test.cc
DEPS
pw_compilation_testing._pigweed_only_negative_compilation
pw_containers.intrusive_list
pw_preprocessor
GROUPS
Expand Down
28 changes: 17 additions & 11 deletions pw_containers/intrusive_list_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
#include <cstdint>

#include "gtest/gtest.h"
#include "pw_compilation_testing/negative_compilation.h"
#include "pw_preprocessor/util.h"

namespace pw {
Expand Down Expand Up @@ -414,7 +415,8 @@ TEST(IntrusiveList, CompareConstAndNonConstIterator) {
EXPECT_EQ(list.end(), list.cend());
}

#if defined(PW_COMPILE_FAIL_TEST_incompatible_iterator_types)
#if PW_NC_TEST(IncompatibleIteratorTypes)
PW_NC_EXPECT("comparison (of|between) distinct pointer types");

struct OtherItem : public IntrusiveList<OtherItem>::Item {};

Expand All @@ -424,11 +426,11 @@ TEST(IntrusiveList, CompareConstAndNonConstIterator_CompilationFails) {
static_cast<void>(list.end() == list2.end());
}

#endif
#endif // PW_NC_TEST

#if PW_NC_TEST(CannotModifyThroughConstIterator)
PW_NC_EXPECT("function is not marked const|discards qualifiers");

// TODO(b/234882063): These tests should fail to compile, enable when no-compile
// tests are set up in Pigweed.
#if defined(PW_COMPILE_FAIL_TEST_cannot_modify_through_const_iterator)
TEST(IntrusiveList, ConstIteratorModify) {
TestItem item1(1);
TestItem item2(99);
Expand All @@ -445,7 +447,7 @@ TEST(IntrusiveList, ConstIteratorModify) {
it++;
}
}
#endif // Compile failure test
#endif // PW_NC_TEST

// TODO(b/235289499): These tests should trigger a CHECK failure. This requires
// using a testing version of pw_assert.
Expand Down Expand Up @@ -675,28 +677,32 @@ TEST(InstrusiveList, ListOfDerivedClassItems) {

EXPECT_EQ(1u, derived_from_compatible_item_type.size());

// TODO(b/234882063): Make these proper automated compilation failure tests.
#if defined(PW_COMPILE_FAIL_TEST_cannot_add_base_class_to_derived_class_list)
#if PW_NC_TEST(CannotAddBaseClassToDerivedClassList)
PW_NC_EXPECT_CLANG("cannot bind to a value of unrelated type");
PW_NC_EXPECT_GCC("cannot convert");

TestItem item2;
derived_from_compatible_item_type.push_front(item2);
#endif
}

#if defined(PW_COMPILE_FAIL_TEST_incompatibile_item_type)
#if PW_NC_TEST(IncompatibileItemType)
PW_NC_EXPECT("IntrusiveList items must be derived from IntrusiveList<T>::Item");

struct Foo {};

class BadItem : public IntrusiveList<Foo>::Item {};

[[maybe_unused]] IntrusiveList<BadItem> derived_from_incompatible_item_type;

#elif defined(PW_COMPILE_FAIL_TEST_does_not_inherit_from_item)
#elif PW_NC_TEST(DoesNotInheritFromItem)
PW_NC_EXPECT("IntrusiveList items must be derived from IntrusiveList<T>::Item");

struct NotAnItem {};

[[maybe_unused]] IntrusiveList<NotAnItem> list;

#endif
#endif // PW_NC_TEST

} // namespace
} // namespace pw
1 change: 1 addition & 0 deletions pw_function/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ pw_test("function_test") {
dir_pw_polyfill,
]
sources = [ "function_test.cc" ]
negative_compilation_tests = true
}

pw_size_report("function_size") {
Expand Down
1 change: 1 addition & 0 deletions pw_function/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ pw_add_test(pw_function.function_test
SOURCES
function_test.cc
DEPS
pw_compilation_testing._pigweed_only_negative_compilation
pw_function
pw_polyfill
GROUPS
Expand Down
16 changes: 10 additions & 6 deletions pw_function/function_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -15,31 +15,35 @@
#include "pw_function/function.h"

#include "gtest/gtest.h"
#include "pw_compilation_testing/negative_compilation.h"
#include "pw_polyfill/language_feature_macros.h"

namespace pw {
namespace {

// TODO(b/234882063): Convert this to a compilation failure test.
#if defined(PW_COMPILE_FAIL_TEST_CannotInstantiateWithNonFunction)
#if PW_NC_TEST(CannotInstantiateWithNonFunction)
PW_NC_EXPECT("pw::Function may only be instantiated for a function type");

[[maybe_unused]] Function<int> function_pointer;

#elif defined(PW_COMPILE_FAIL_TEST_CannotInstantiateWithFunctionPointer1)
#elif PW_NC_TEST(CannotInstantiateWithFunctionPointer1)
PW_NC_EXPECT("pw::Function may only be instantiated for a function type");

[[maybe_unused]] Function<void (*)()> function_pointer;

#elif defined(PW_COMPILE_FAIL_TEST_CannotInstantiateWithFunctionPointer2)
#elif PW_NC_TEST(CannotInstantiateWithFunctionPointer2)
PW_NC_EXPECT("pw::Function may only be instantiated for a function type");

[[maybe_unused]] void SomeFunction(int);

[[maybe_unused]] Function<decltype(&SomeFunction)> function_pointer;

#elif defined(PW_COMPILE_FAIL_TEST_CannotInstantiateWithFunctionReference)
#elif PW_NC_TEST(CannotInstantiateWithFunctionReference)
PW_NC_EXPECT("pw::Function may only be instantiated for a function type");

[[maybe_unused]] Function<void (&)()> function_pointer;

#endif // compile fail tests
#endif // PW_NC_TEST

// Ensure that Function can be constant initialized.
[[maybe_unused]] PW_CONSTINIT Function<void()> can_be_constant_initialized;
Expand Down
2 changes: 1 addition & 1 deletion pw_function/public/pw_function/function.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ namespace pw {
template <typename Callable>
class Function {
static_assert(std::is_function_v<Callable>,
"pw::Function may only be instantianted for a function type, "
"pw::Function may only be instantiated for a function type, "
"such as pw::Function<void(int)>.");
};

Expand Down
1 change: 1 addition & 0 deletions pw_rpc/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import("$dir_pw_build/python.gni")
import("$dir_pw_build/python_action.gni")
import("$dir_pw_build/target_types.gni")
import("$dir_pw_chrono/backend.gni")
import("$dir_pw_compilation_testing/negative_compilation_test.gni")
import("$dir_pw_docgen/docs.gni")
import("$dir_pw_protobuf_compiler/proto.gni")
import("$dir_pw_sync/backend.gni")
Expand Down
8 changes: 8 additions & 0 deletions pw_rpc/raw/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,14 @@ pw_cc_test(
],
)

# Negative compilation testing is not supported by Bazel. Build this as a
# regular unit for now test.
pw_cc_test(
name = "service_nc_test",
srcs = ["service_nc_test.cc"],
deps = ["//pw_rpc:pw_rpc_test_cc.raw_rpc"],
)

pw_cc_test(
name = "stub_generation_test",
srcs = ["stub_generation_test.cc"],
Expand Down
7 changes: 7 additions & 0 deletions pw_rpc/raw/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
import("//build_overrides/pigweed.gni")

import("$dir_pw_build/target_types.gni")
import("$dir_pw_compilation_testing/negative_compilation_test.gni")
import("$dir_pw_docgen/docs.gni")
import("$dir_pw_unit_test/test.gni")

Expand Down Expand Up @@ -119,6 +120,7 @@ pw_test("client_reader_writer_test") {
pw_test("method_test") {
deps = [
":server_api",
":service_nc_test", # Pull in the service NC test through this test
"$dir_pw_containers",
"..:test_protos.pwpb",
"..:test_protos.raw_rpc",
Expand Down Expand Up @@ -160,3 +162,8 @@ pw_test("stub_generation_test") {
deps = [ "..:test_protos.raw_rpc" ]
sources = [ "stub_generation_test.cc" ]
}

pw_cc_negative_compilation_test("service_nc_test") {
sources = [ "service_nc_test.cc" ]
deps = [ "..:test_protos.raw_rpc" ]
}
1 change: 1 addition & 0 deletions pw_rpc/raw/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ pw_auto_add_simple_module(pw_rpc.raw
pw_rpc.common
pw_rpc.server
TEST_DEPS
pw_compilation_testing._pigweed_only_negative_compilation
pw_rpc.test_protos.pwpb
pw_rpc.test_protos.raw_rpc
pw_rpc.test_utils
Expand Down
38 changes: 38 additions & 0 deletions pw_rpc/raw/service_nc_test.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
// Copyright 2021 The Pigweed Authors
//
// 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
//
// https://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.

#include "pw_compilation_testing/negative_compilation.h"
#include "pw_rpc_test_protos/test.raw_rpc.pb.h"

namespace pw::rpc {
namespace test {

#if PW_NC_TEST(NoMethods)
PW_NC_EXPECT("TestUnaryRpc");

class TestService final
: public pw_rpc::raw::TestService::Service<TestService> {
public:
};

#else

class TestService {};

#endif // PW_NC_TEST

TestService test_service;

} // namespace test
} // namespace pw::rpc
10 changes: 6 additions & 4 deletions pw_unit_test/static_library_support_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -41,15 +41,17 @@ class CheckThatTestsRanWhenDestructed {
}
} check_that_tests_ran;

// TODO(b/234882063): Convert this to a compilation failure test.
#if defined(PW_COMPILE_FAIL_TEST_FailsToLinkInvalidTestSuite)
// Test that linking fails if these macros refer to tests that do not exist.
// These cannot be a negative compilation tests because they compile
// successfully, but fail to link.
#if 0

PW_UNIT_TEST_LINK_FILE_CONTAINING_TEST(NotARealSuite, NotARealTest);

#elif defined(PW_COMPILE_FAIL_TEST_FailsToLinkInvalidTestName)
#elif 0

PW_UNIT_TEST_LINK_FILE_CONTAINING_TEST(StaticLibraryArchivedTest, NotARealTest);

#endif // compile fail tests
#endif // negative linking tests

} // namespace pw::unit_test
3 changes: 2 additions & 1 deletion targets/host/target_toolchains.gni
Original file line number Diff line number Diff line change
Expand Up @@ -307,7 +307,8 @@ pw_target_toolchain_host_list = [
_pigweed_internal = {
pw_status_CONFIG = "$dir_pw_status:check_if_used"

pw_compilation_testing_NEGATIVE_COMPILATION_ENABLED = true
# TODO(b/241565082): Enable NC testing in GN Windows when it is fixed.
pw_compilation_testing_NEGATIVE_COMPILATION_ENABLED = host_os != "win"
}

# Host toolchains exclusively for upstream Pigweed use. To give upstream Pigweed
Expand Down
3 changes: 2 additions & 1 deletion targets/stm32f429i_disc1/target_toolchains.gni
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,8 @@ declare_args() {
}

_target_config = {
pw_compilation_testing_NEGATIVE_COMPILATION_ENABLED = true
# TODO(b/241565082): Enable NC testing in GN Windows when it is fixed.
pw_compilation_testing_NEGATIVE_COMPILATION_ENABLED = host_os != "win"

# Use the logging main.
pw_unit_test_MAIN = "$dir_pw_unit_test:logging_main"
Expand Down

0 comments on commit 1b7adca

Please sign in to comment.