blob: f785fd33c0b839097e984084b7e5ab14db68d37a [file] [log] [blame]
// Copyright 2025 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_assert/assert.h"
#include "pw_compilation_testing/negative_compilation.h"
#include "pw_polyfill/standard.h"
#include "pw_unit_test/framework.h"
namespace {
template <int kValue>
struct MyStruct {
static_assert(kValue % 2 == 0, "wrong number!");
constexpr MyStruct() = default;
MyStruct(int) {} // non-constexpr constructor
constexpr int MultiplyOdd(int runtime_value) const {
PW_ASSERT(runtime_value % 2 == 1);
return kValue * runtime_value;
}
};
[[maybe_unused]] MyStruct<16> this_one_works;
// NC tests cannot be compiled, so they are created in preprocessor #if or
// #elif blocks. These NC tests check that a static_assert statement fails if
// the code is compiled.
#if PW_NC_TEST(NegativeOddNumber)
PW_NC_EXPECT("wrong number!");
[[maybe_unused]] MyStruct<-1> illegal;
#elif PW_NC_TEST(PositiveOddNumber)
PW_NC_EXPECT("wrong number!");
[[maybe_unused]] MyStruct<5> this_is_illegal;
#endif // PW_NC_TEST
struct Foo {
// Negative compilation tests can go anywhere in a source file.
#if PW_NC_TEST(IllegalValueAsClassMember)
PW_NC_EXPECT("wrong number!");
MyStruct<13> also_illegal;
#endif // PW_NC_TEST
};
// Negative compilation tests can be integrated with standard unit tests.
TEST(MyStruct, MultiplyOdd) {
constexpr MyStruct<6> six;
EXPECT_EQ(six.MultiplyOdd(3), 18);
// This NC test checks that a specific PW_ASSERT() fails when expected.
// This only works in an NC test if the PW_ASSERT() fails while the compiler
// is executing constexpr code. The test code is used in a constexpr
// statement to force compile-time evaluation.
#if PW_NC_TEST(MyStruct_MultiplyOdd_AssertsOnOddNumber)
PW_NC_EXPECT("PW_ASSERT\(runtime_value % 2 == 1\);");
[[maybe_unused]] constexpr auto fail = [&six] {
return six.MultiplyOdd(4); // Even number, PW_ASSERT should fail.
}();
#endif // PW_NC_TEST
}
// PW_NC_TESTs can be skipped by commenting them out or using `#if 0`.
#if PW_CXX_STANDARD_IS_SUPPORTED(20)
#if PW_NC_TEST(DoesNotCompile)
PW_NC_EXPECT("PW_ASSERT_failed_in_constant_expression_");
[[maybe_unused]] constinit MyStruct<12> should_fail = [] {
MyStruct<12> example;
example.MultiplyOdd(2);
return example;
}();
#endif // PW_NC_TEST
#endif // PW_CXX_STANDARD_IS_SUPPORTED(20)
} // namespace