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