xref: /aosp_15_r20/external/pigweed/pw_bytes/packed_ptr_test.cc (revision 61c4878ac05f98d0ceed94b57d316916de578985)
1 
2 // Copyright 2022 The Pigweed Authors
3 //
4 // Licensed under the Apache License, Version 2.0 (the "License"); you may not
5 // use this file except in compliance with the License. You may obtain a copy of
6 // the License at
7 //
8 //     https://www.apache.org/licenses/LICENSE-2.0
9 //
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12 // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13 // License for the specific language governing permissions and limitations under
14 // the License.
15 
16 #include "pw_bytes/packed_ptr.h"
17 
18 #include <cstdint>
19 
20 #include "pw_compilation_testing/negative_compilation.h"
21 #include "pw_unit_test/framework.h"
22 
23 namespace {
24 
25 template <size_t kAlign>
26 struct alignas(kAlign) Aligned {
27   uint16_t val_ = 0;
28 };
29 
TEST(PackedPtrTest,NumBits)30 TEST(PackedPtrTest, NumBits) {
31   EXPECT_EQ(pw::PackedPtr<Aligned<2>>::NumBits(), 1U);
32   EXPECT_EQ(pw::PackedPtr<Aligned<4>>::NumBits(), 2U);
33   EXPECT_EQ(pw::PackedPtr<Aligned<8>>::NumBits(), 3U);
34   EXPECT_EQ(pw::PackedPtr<Aligned<16>>::NumBits(), 4U);
35   EXPECT_EQ(pw::PackedPtr<Aligned<32>>::NumBits(), 5U);
36   EXPECT_EQ(pw::PackedPtr<Aligned<64>>::NumBits(), 6U);
37   EXPECT_EQ(pw::PackedPtr<Aligned<128>>::NumBits(), 7U);
38   EXPECT_EQ(pw::PackedPtr<Aligned<256>>::NumBits(), 8U);
39 }
40 
41 #if PW_NC_TEST(NumBits_AlignmentIsOne)
42 PW_NC_EXPECT("Alignment must be more than one to pack any bits");
TEST(PackedPtrTest,NumBits_Char)43 TEST(PackedPtrTest, NumBits_Char) {
44   EXPECT_EQ(pw::PackedPtr<char>::NumBits(), 0U);
45 }
46 #elif PW_NC_TEST(Construct_AlignmentIsOne)
47 PW_NC_EXPECT("Alignment must be more than one to pack any bits");
48 [[maybe_unused]] pw::PackedPtr<std::byte> bad;
49 #endif  // PW_NC_TEST
50 
TEST(PackedPtrTest,Construct_Default)51 TEST(PackedPtrTest, Construct_Default) {
52   pw::PackedPtr<Aligned<4>> ptr;
53   EXPECT_EQ(ptr.get(), nullptr);
54   EXPECT_EQ(ptr.packed_value(), 0U);
55 }
56 
TEST(PackedPtrTest,Construct_FromArgs)57 TEST(PackedPtrTest, Construct_FromArgs) {
58   Aligned<16> obj;
59   pw::PackedPtr ptr(&obj, 1);
60   EXPECT_EQ(ptr.get(), &obj);
61   EXPECT_EQ(ptr.packed_value(), 1U);
62 }
63 
TEST(PackedPtrTest,Construct_Copy)64 TEST(PackedPtrTest, Construct_Copy) {
65   Aligned<16> obj;
66   pw::PackedPtr ptr1(&obj, 2);
67   pw::PackedPtr ptr2(ptr1);
68   EXPECT_EQ(ptr1.get(), &obj);
69   EXPECT_EQ(ptr1.packed_value(), 2U);
70   EXPECT_EQ(ptr2.get(), &obj);
71   EXPECT_EQ(ptr2.packed_value(), 2U);
72 }
73 
TEST(PackedPtrTest,Construct_Copy_AddConst)74 TEST(PackedPtrTest, Construct_Copy_AddConst) {
75   Aligned<16> obj;
76   pw::PackedPtr ptr1(&obj, 2);
77   pw::PackedPtr<const Aligned<16>> ptr2(ptr1);
78   EXPECT_EQ(ptr1.get(), &obj);
79   EXPECT_EQ(ptr1.packed_value(), 2U);
80   EXPECT_EQ(ptr2.get(), &obj);
81   EXPECT_EQ(ptr2.packed_value(), 2U);
82 }
83 
TEST(PackedPtrTest,Construct_Move)84 TEST(PackedPtrTest, Construct_Move) {
85   Aligned<16> obj;
86   pw::PackedPtr ptr1(&obj, 3);
87   pw::PackedPtr ptr2(std::move(ptr1));
88   // NOLINTBEGIN(bugprone-use-after-move)
89   EXPECT_EQ(ptr1.get(), nullptr);
90   EXPECT_EQ(ptr1.packed_value(), 0U);
91   // NOLINTEND(bugprone-use-after-move)
92   EXPECT_EQ(ptr2.get(), &obj);
93   EXPECT_EQ(ptr2.packed_value(), 3U);
94 }
95 
TEST(PackedPtrTest,Construct_Move_AddConst)96 TEST(PackedPtrTest, Construct_Move_AddConst) {
97   Aligned<16> obj;
98   pw::PackedPtr ptr1(&obj, 3);
99   pw::PackedPtr<const Aligned<16>> ptr2(std::move(ptr1));
100   // NOLINTBEGIN(bugprone-use-after-move)
101   EXPECT_EQ(ptr1.get(), nullptr);
102   EXPECT_EQ(ptr1.packed_value(), 0U);
103   // NOLINTEND(bugprone-use-after-move)
104   EXPECT_EQ(ptr2.get(), &obj);
105   EXPECT_EQ(ptr2.packed_value(), 3U);
106 }
107 
108 // Ensure we can create PackedPtrs to types that include PackedPtrs to
109 // themsevles.
110 struct Recursive {
111   size_t field_ = 0;
112   pw::PackedPtr<Recursive> ptr_;
113 };
114 
TEST(PackedPtrTest,Construct_Recursive)115 TEST(PackedPtrTest, Construct_Recursive) {
116   pw::PackedPtr<Recursive> ptr;
117   EXPECT_EQ(ptr.get(), nullptr);
118   EXPECT_EQ(ptr.packed_value(), 0U);
119 }
120 
TEST(PackedPtrTest,Copy)121 TEST(PackedPtrTest, Copy) {
122   Aligned<16> obj;
123   pw::PackedPtr ptr1(&obj, 4);
124   pw::PackedPtr ptr2 = ptr1;
125   EXPECT_EQ(ptr1.get(), &obj);
126   EXPECT_EQ(ptr1.packed_value(), 4U);
127   EXPECT_EQ(ptr2.get(), &obj);
128   EXPECT_EQ(ptr2.packed_value(), 4U);
129 }
130 
TEST(PackedPtrTest,Copy_AddConst)131 TEST(PackedPtrTest, Copy_AddConst) {
132   Aligned<16> obj;
133   pw::PackedPtr ptr1(&obj, 4);
134   pw::PackedPtr<const Aligned<16>> ptr2 = ptr1;
135   EXPECT_EQ(ptr1.get(), &obj);
136   EXPECT_EQ(ptr1.packed_value(), 4U);
137   EXPECT_EQ(ptr2.get(), &obj);
138   EXPECT_EQ(ptr2.packed_value(), 4U);
139 }
140 
TEST(PackedPtrTest,Move)141 TEST(PackedPtrTest, Move) {
142   Aligned<16> obj;
143   pw::PackedPtr ptr1(&obj, 6);
144   pw::PackedPtr ptr2 = std::move(ptr1);
145   // NOLINTBEGIN(bugprone-use-after-move)
146   EXPECT_EQ(ptr1.get(), nullptr);
147   EXPECT_EQ(ptr1.packed_value(), 0U);
148   // NOLINTEND(bugprone-use-after-move)
149   EXPECT_EQ(ptr2.get(), &obj);
150   EXPECT_EQ(ptr2.packed_value(), 6U);
151 }
152 
TEST(PackedPtrTest,Move_AddConst)153 TEST(PackedPtrTest, Move_AddConst) {
154   Aligned<16> obj;
155   pw::PackedPtr ptr1(&obj, 6);
156   pw::PackedPtr<const Aligned<16>> ptr2 = std::move(ptr1);
157   // NOLINTBEGIN(bugprone-use-after-move)
158   EXPECT_EQ(ptr1.get(), nullptr);
159   EXPECT_EQ(ptr1.packed_value(), 0U);
160   // NOLINTEND(bugprone-use-after-move)
161   EXPECT_EQ(ptr2.get(), &obj);
162   EXPECT_EQ(ptr2.packed_value(), 6U);
163 }
164 
TEST(PackedPtrTest,Dereference)165 TEST(PackedPtrTest, Dereference) {
166   Aligned<4> obj{1u};
167   pw::PackedPtr ptr(&obj, 0);
168   EXPECT_EQ((*ptr).val_, 1u);
169 }
170 
TEST(PackedPtrTest,Dereference_Const)171 TEST(PackedPtrTest, Dereference_Const) {
172   Aligned<4> obj{22u};
173   const pw::PackedPtr ptr(&obj, 0);
174   EXPECT_EQ((*ptr).val_, 22u);
175 }
176 
TEST(PackedPtrTest,StructureDereference)177 TEST(PackedPtrTest, StructureDereference) {
178   Aligned<4> obj{333u};
179   pw::PackedPtr ptr(&obj, 0);
180   EXPECT_EQ(ptr->val_, 333u);
181 }
182 
TEST(PackedPtrTest,StructureDereference_Const)183 TEST(PackedPtrTest, StructureDereference_Const) {
184   Aligned<4> obj{4444u};
185   const pw::PackedPtr ptr(&obj, 0);
186   EXPECT_EQ(ptr->val_, 4444u);
187 }
188 
189 }  // namespace
190