• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2022 The Pigweed Authors
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License"); you may not
4 // use this file except in compliance with the License. You may obtain a copy of
5 // the License at
6 //
7 //     https://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11 // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12 // License for the specific language governing permissions and limitations under
13 // the License.
14 
15 #include "pw_toolchain/no_destructor.h"
16 
17 #include "gtest/gtest.h"
18 #include "pw_assert/check.h"
19 
20 namespace pw {
21 namespace {
22 
23 class HasADestructor {
24  public:
HasADestructor(bool & destructor_called_flag)25   HasADestructor(bool& destructor_called_flag)
26       : destructor_called_(destructor_called_flag) {
27     destructor_called_ = false;
28   }
29 
~HasADestructor()30   ~HasADestructor() { destructor_called_ = true; }
31 
32  private:
33   bool& destructor_called_;
34 };
35 
36 class CrashInDestructor {
37  public:
MyAddress() const38   const CrashInDestructor* MyAddress() const { return this; }
39 
40   int some_value = 0;
41 
42  private:
~CrashInDestructor()43   ~CrashInDestructor() { PW_CRASH("This destructor should never execute!"); }
44 };
45 
TEST(NoDestructor,ShouldNotCallDestructor)46 TEST(NoDestructor, ShouldNotCallDestructor) {
47   bool destructor_called = false;
48 
49   { HasADestructor should_be_destroyed(destructor_called); }
50 
51   EXPECT_TRUE(destructor_called);
52 
53   { NoDestructor<HasADestructor> should_not_be_destroyed(destructor_called); }
54 
55   EXPECT_FALSE(destructor_called);
56 }
57 
TEST(NoDestructor,MemberAccess)58 TEST(NoDestructor, MemberAccess) {
59   NoDestructor<CrashInDestructor> no_destructor;
60 
61   no_destructor->some_value = 123;
62   EXPECT_EQ(123, (*no_destructor).some_value);
63   EXPECT_EQ(no_destructor.operator->(), no_destructor->MyAddress());
64 }
65 
TEST(NoDestructor,TrivialType)66 TEST(NoDestructor, TrivialType) {
67   NoDestructor<int> no_destructor;
68 
69   EXPECT_EQ(*no_destructor, 0);
70   *no_destructor = 123;
71   EXPECT_EQ(*no_destructor, 123);
72 }
73 
TEST(NoDestructor,FunctionStatic)74 TEST(NoDestructor, FunctionStatic) {
75   static NoDestructor<CrashInDestructor> function_static_no_destructor;
76 }
77 
78 NoDestructor<CrashInDestructor> global_no_destructor;
79 
80 static_assert(!std::is_trivially_destructible<CrashInDestructor>::value,
81               "Type should not be trivially destructible");
82 static_assert(
83     std::is_trivially_destructible<NoDestructor<CrashInDestructor>>::value,
84     "Wrapper should be trivially destructible");
85 
86 }  // namespace
87 }  // namespace pw
88