• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2023 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 <numeric>
16 
17 #include "lib/stdcompat/utility.h"
18 #include "pw_unit_test/framework.h"  // IWYU pragma: keep
19 
20 // clang-format off
21 // All emboss headers are listed (even if they don't have explicit tests) to
22 // ensure they are compiled.
23 #include "pw_bluetooth/hci_commands.emb.h"  // IWYU pragma: keep
24 #include "pw_bluetooth/hci_common.emb.h"
25 #include "pw_bluetooth/hci_data.emb.h"
26 #include "pw_bluetooth/hci_events.emb.h"  // IWYU pragma: keep
27 #include "pw_bluetooth/hci_h4.emb.h"      // IWYU pragma: keep
28 #include "pw_bluetooth/hci_test.emb.h"
29 #include "pw_bluetooth/hci_android.emb.h"    // IWYU pragma: keep
30 #include "pw_bluetooth/l2cap_frames.emb.h"  // IWYU pragma: keep
31 // clang-format on
32 
33 namespace pw::bluetooth {
34 namespace {
35 
36 // Examples are used in docs.rst.
TEST(EmbossExamples,MakeView)37 TEST(EmbossExamples, MakeView) {
38   // DOCSTAG: [pw_bluetooth-examples-make_view]
39   std::array<uint8_t, 4> buffer = {0x00, 0x01, 0x02, 0x03};
40   auto view = emboss::MakeTestCommandPacketView(&buffer);
41   EXPECT_TRUE(view.IsComplete());
42   EXPECT_EQ(view.payload().Read(), 0x03);
43   // DOCSTAG: [pw_bluetooth-examples-make_view]
44 }
45 
TEST(EmbossTest,MakeView)46 TEST(EmbossTest, MakeView) {
47   std::array<uint8_t, 4> buffer = {0x00, 0x01, 0x02, 0x03};
48   auto view = emboss::MakeTestCommandPacketView(&buffer);
49   EXPECT_TRUE(view.IsComplete());
50   EXPECT_EQ(view.payload().Read(), 0x03);
51 }
52 
53 // This definition has a mix of full-width values and bitfields and includes
54 // conditional bitfields. Let's add this to verify that the structure itself
55 // doesn't get changed incorrectly and that emboss' size calculation matches
56 // ours.
TEST(EmbossTest,CheckIsoHeaderSize)57 TEST(EmbossTest, CheckIsoHeaderSize) {
58   EXPECT_EQ(emboss::IsoDataFrameHeader::MaxSizeInBytes(), 12);
59 }
60 
61 // Test and demonstrate various ways of reading opcodes.
TEST(EmbossTest,ReadOpcodesFromCommandHeader)62 TEST(EmbossTest, ReadOpcodesFromCommandHeader) {
63   // First two bytes will be used as opcode.
64   std::array<uint8_t, 4> buffer = {0x00, 0x00, 0x02, 0x03};
65   auto view = emboss::MakeTestCommandPacketView(&buffer);
66   EXPECT_TRUE(view.IsComplete());
67   auto header = view.header();
68 
69   EXPECT_EQ(header.opcode_enum().Read(), emboss::OpCode::UNSPECIFIED);
70   EXPECT_EQ(header.opcode().BackingStorage().ReadUInt(), 0x0000);
71   EXPECT_EQ(header.opcode_bits().ogf().Read(), 0x00);
72   EXPECT_EQ(header.opcode_bits().ocf().Read(), 0x00);
73   // TODO: https://pwbug.dev/338068316 - Delete these opcode type
74   // OpCodeBits cases once opcode has type OpCode.
75   EXPECT_EQ(header.opcode().ogf().Read(), 0x00);
76   EXPECT_EQ(header.opcode().ocf().Read(), 0x00);
77 
78   // LINK_KEY_REQUEST_REPLY is OGF 0x01 and OCF 0x0B.
79   header.opcode_enum().Write(emboss::OpCode::LINK_KEY_REQUEST_REPLY);
80   EXPECT_EQ(header.opcode_enum().Read(),
81             emboss::OpCode::LINK_KEY_REQUEST_REPLY);
82   EXPECT_EQ(header.opcode().BackingStorage().ReadUInt(), 0x040B);
83   EXPECT_EQ(header.opcode_bits().ogf().Read(), 0x01);
84   EXPECT_EQ(header.opcode_bits().ocf().Read(), 0x0B);
85   // TODO: https://pwbug.dev/338068316 - Delete these opcode type
86   // OpCodeBits cases once opcode has type OpCode.
87   EXPECT_EQ(header.opcode().ogf().Read(), 0x01);
88   EXPECT_EQ(header.opcode().ocf().Read(), 0x0B);
89 }
90 
91 // Test and demonstrate various ways of writing opcodes.
TEST(EmbossTest,WriteOpcodesFromCommandHeader)92 TEST(EmbossTest, WriteOpcodesFromCommandHeader) {
93   std::array<uint8_t, 4> buffer = {};
94   buffer.fill(0xFF);
95   auto view = emboss::MakeTestCommandPacketView(&buffer);
96   EXPECT_TRUE(view.IsComplete());
97   auto header = view.header();
98 
99   header.opcode_enum().Write(emboss::OpCode::UNSPECIFIED);
100   EXPECT_EQ(header.opcode().BackingStorage().ReadUInt(), 0x0000);
101 
102   header.opcode().ocf().Write(0x0B);
103   EXPECT_EQ(header.opcode().BackingStorage().ReadUInt(), 0x000B);
104 
105   header.opcode().ogf().Write(0x01);
106   EXPECT_EQ(header.opcode().BackingStorage().ReadUInt(), 0x040B);
107   // LINK_KEY_REQUEST_REPLY is OGF 0x01 and OCF 0x0B.
108   EXPECT_EQ(header.opcode_enum().Read(),
109             emboss::OpCode::LINK_KEY_REQUEST_REPLY);
110 }
111 
112 // Test and demonstrate using to_underlying with OpCodes enums
TEST(EmbossTest,OPCodeEnumsWithToUnderlying)113 TEST(EmbossTest, OPCodeEnumsWithToUnderlying) {
114   EXPECT_EQ(0x0000, cpp23::to_underlying(emboss::OpCode::UNSPECIFIED));
115 }
116 
TEST(EmbossTest,ReadAndWriteOpcodesInCommandResponseHeader)117 TEST(EmbossTest, ReadAndWriteOpcodesInCommandResponseHeader) {
118   // First two bytes will be used as opcode.
119   std::array<uint8_t,
120              emboss::ReadBufferSizeCommandCompleteEventView::SizeInBytes()>
121       buffer;
122   std::iota(buffer.begin(), buffer.end(), 100);
123   auto view = emboss::MakeReadBufferSizeCommandCompleteEventView(&buffer);
124   EXPECT_TRUE(view.IsComplete());
125   auto header = view.command_complete();
126 
127   header.command_opcode().BackingStorage().WriteUInt(0x0000);
128   EXPECT_EQ(header.command_opcode_enum().Read(), emboss::OpCode::UNSPECIFIED);
129   EXPECT_EQ(header.command_opcode().BackingStorage().ReadUInt(), 0x0000);
130   EXPECT_EQ(header.command_opcode_bits().ogf().Read(), 0x00);
131   EXPECT_EQ(header.command_opcode_bits().ocf().Read(), 0x00);
132   // TODO: https://pwbug.dev/338068316 - Delete these command_opcode type
133   // OpCodeBits cases once command_opcode has type OpCode.
134   EXPECT_EQ(header.command_opcode().ogf().Read(), 0x00);
135   EXPECT_EQ(header.command_opcode().ocf().Read(), 0x00);
136 
137   // LINK_KEY_REQUEST_REPLY is OGF 0x01 and OCF 0x0B.
138   header.command_opcode_enum().Write(emboss::OpCode::LINK_KEY_REQUEST_REPLY);
139   EXPECT_EQ(header.command_opcode_enum().Read(),
140             emboss::OpCode::LINK_KEY_REQUEST_REPLY);
141   EXPECT_EQ(header.command_opcode().BackingStorage().ReadUInt(), 0x040B);
142   EXPECT_EQ(header.command_opcode_bits().ogf().Read(), 0x01);
143   EXPECT_EQ(header.command_opcode_bits().ocf().Read(), 0x0B);
144   // TODO: https://pwbug.dev/338068316 - Delete these command_opcode type
145   // OpCodeBits cases once command_opcode has type OpCode.
146   EXPECT_EQ(header.command_opcode().ogf().Read(), 0x01);
147   EXPECT_EQ(header.command_opcode().ocf().Read(), 0x0B);
148 }
149 
TEST(EmbossTest,ReadAndWriteEventCodesInEventHeader)150 TEST(EmbossTest, ReadAndWriteEventCodesInEventHeader) {
151   std::array<uint8_t, emboss::EventHeaderWriter::SizeInBytes()> buffer;
152   std::iota(buffer.begin(), buffer.end(), 100);
153   auto header = emboss::MakeEventHeaderView(&buffer);
154   EXPECT_TRUE(header.IsComplete());
155 
156   header.event_code_uint().Write(
157       cpp23::to_underlying(emboss::EventCode::NUMBER_OF_COMPLETED_PACKETS));
158   EXPECT_EQ(header.event_code_enum().Read(),
159             emboss::EventCode::NUMBER_OF_COMPLETED_PACKETS);
160   EXPECT_EQ(
161       header.event_code_uint().Read(),
162       cpp23::to_underlying(emboss::EventCode::NUMBER_OF_COMPLETED_PACKETS));
163 
164   // TODO: https://pwbug.dev/338068316 - Delete these event_code type
165   // UInt cases once event_code has type EventCode.
166   EXPECT_EQ(
167       header.event_code().Read(),
168       cpp23::to_underlying(emboss::EventCode::NUMBER_OF_COMPLETED_PACKETS));
169 
170   header.event_code().Write(
171       cpp23::to_underlying(emboss::EventCode::CONNECTION_REQUEST));
172   EXPECT_EQ(header.event_code_uint().Read(),
173             cpp23::to_underlying(emboss::EventCode::CONNECTION_REQUEST));
174 }
175 
176 }  // namespace
177 }  // namespace pw::bluetooth
178