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