1 // Copyright 2024 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_bluetooth/snoop.h"
16
17 #include <vector>
18
19 #include "pw_bluetooth_proxy/h4_packet.h"
20 #include "pw_bytes/span.h"
21 #include "pw_chrono/simulated_system_clock.h"
22 #include "pw_status/status.h"
23 #include "pw_unit_test/framework.h"
24
25 namespace pw::bluetooth {
26 namespace {
27 using ::std::chrono_literals::operator""us;
28
hex_char_to_int(char c)29 constexpr uint8_t hex_char_to_int(char c) {
30 if (c >= '0' && c <= '9') {
31 return c - '0';
32 } else if (c >= 'a' && c <= 'f') {
33 return c - 'a' + 10;
34 } else if (c >= 'A' && c <= 'F') {
35 return c - 'A' + 10;
36 } else {
37 // Handle invalid characters as needed
38 return 0;
39 }
40 }
41
hex_string_to_bytes(std::string_view hex_str)42 std::vector<std::byte> hex_string_to_bytes(std::string_view hex_str) {
43 std::vector<std::byte> bytes{};
44 uint8_t value = 0;
45 for (size_t i = 0; i < hex_str.size(); i++) {
46 if (i % 2 == 0) {
47 value = hex_char_to_int(hex_str[i]) << 4;
48 } else {
49 value |= hex_char_to_int(hex_str[i]);
50 bytes.push_back(std::byte(value));
51 }
52 }
53 return bytes;
54 }
55
TEST(SnoopTest,HeaderOnly)56 TEST(SnoopTest, HeaderOnly) {
57 chrono::SimulatedSystemClock clock{};
58 SnoopBuffer<4096, 256> snoop{clock};
59 std::vector<std::byte> snoop_data;
60 Status status = snoop.Dump([&snoop_data](ConstByteSpan data) {
61 for (const std::byte item : data) {
62 snoop_data.push_back(item);
63 }
64 return OkStatus();
65 });
66 EXPECT_TRUE(status.ok());
67
68 std::string_view expected_snoop_data = // Identification Pattern (64-bit)
69 "6274736e6f6f7000"
70 // Version Number (32-bit)
71 "00000001"
72 // Datalink Type (32-bit)
73 "000003ea";
74 EXPECT_EQ(hex_string_to_bytes(expected_snoop_data), snoop_data);
75 }
76
TEST(SnoopTest,HeaderTx)77 TEST(SnoopTest, HeaderTx) {
78 chrono::SimulatedSystemClock clock{};
79 SnoopBuffer<4096, 256> snoop{clock};
80
81 // Add packet 1
82 std::array<uint8_t, 5> tx_data = {0x12, 0x34, 0x56, 0x78, 0x9A};
83 proxy::H4PacketWithHci packet{emboss::H4PacketType::ACL_DATA, tx_data};
84 snoop.AddTx(packet);
85
86 // Get snoop log
87 std::vector<std::byte> snoop_data;
88 Status status = snoop.Dump([&snoop_data](ConstByteSpan data) {
89 for (const std::byte item : data) {
90 snoop_data.push_back(item);
91 }
92 return OkStatus();
93 });
94 EXPECT_TRUE(status.ok());
95
96 // Validate
97 std::string_view expected_snoop_data =
98 ""
99 // Identification Pattern (64-bit)
100 "6274736e6f6f7000"
101 // Version Number (32-bit)
102 "00000001"
103 // Datalink Type (32-bit)
104 "000003ea"
105 // Packet 1
106 // Original Length (32-bit)
107 "00000006"
108 // Included Length (32-bit)
109 "00000006"
110 // Packet Flags (32-bit)
111 "00000000"
112 // Cumulative Drops (32-bit)
113 "00000000"
114 // Timestamp Microseconds (64-bit)
115 "0000000000000000"
116 // Packet Data[0] - HCI_TYPE (8-bit)
117 "02"
118 // Packet Data[1-N] - Data
119 "123456789a";
120 EXPECT_EQ(hex_string_to_bytes(expected_snoop_data), snoop_data);
121 }
122
TEST(SnoopTest,HeaderTxTruncated)123 TEST(SnoopTest, HeaderTxTruncated) {
124 chrono::SimulatedSystemClock clock{};
125 SnoopBuffer<4096, 3> snoop{clock};
126
127 // Add packet 1
128 std::array<uint8_t, 5> tx_data = {0x12, 0x34, 0x56, 0x78, 0x9A};
129 proxy::H4PacketWithHci packet{emboss::H4PacketType::ACL_DATA, tx_data};
130 snoop.AddTx(packet);
131
132 // Get snoop log
133 std::vector<std::byte> snoop_data;
134 Status status = snoop.Dump([&snoop_data](ConstByteSpan data) {
135 for (const std::byte item : data) {
136 snoop_data.push_back(item);
137 }
138 return OkStatus();
139 });
140 EXPECT_TRUE(status.ok());
141
142 // Validate
143 std::string_view expected_snoop_data =
144 ""
145 // Identification Pattern (64-bit)
146 "6274736e6f6f7000"
147 // Version Number (32-bit)
148 "00000001"
149 // Datalink Type (32-bit)
150 "000003ea"
151 // Packet 1
152 // Original Length (32-bit)
153 "00000006"
154 // Included Length (32-bit)
155 "00000004"
156 // Packet Flags (32-bit)
157 "00000000"
158 // Cumulative Drops (32-bit)
159 "00000000"
160 // Timestamp Microseconds (64-bit)
161 "0000000000000000"
162 // Packet Data[0] - HCI_TYPE (8-bit)
163 "02"
164 // Packet Data[1-N] - Data
165 "123456";
166 EXPECT_EQ(hex_string_to_bytes(expected_snoop_data), snoop_data);
167 }
168
TEST(SnoopTest,HeaderRx)169 TEST(SnoopTest, HeaderRx) {
170 chrono::SimulatedSystemClock clock{};
171 SnoopBuffer<4096, 256> snoop{clock};
172
173 // Add packet 1
174 std::array<uint8_t, 5> rx_data = {0x12, 0x34, 0x56, 0x78, 0x9A};
175 proxy::H4PacketWithHci packet{emboss::H4PacketType::ACL_DATA, rx_data};
176 snoop.AddRx(packet);
177
178 // Get snoop log
179 std::vector<std::byte> snoop_data;
180 Status status = snoop.Dump([&snoop_data](ConstByteSpan data) {
181 for (const std::byte item : data) {
182 snoop_data.push_back(item);
183 }
184 return OkStatus();
185 });
186 EXPECT_TRUE(status.ok());
187
188 // Validate
189 std::string_view expected_snoop_data =
190 ""
191 // Identification Pattern (64-bit)
192 "6274736e6f6f7000"
193 // Version Number (32-bit)
194 "00000001"
195 // Datalink Type (32-bit)
196 "000003ea"
197 // Packet 1
198 // Original Length (32-bit)
199 "00000006"
200 // Included Length (32-bit)
201 "00000006"
202 // Packet Flags (32-bit)
203 "00000001"
204 // Cumulative Drops (32-bit)
205 "00000000"
206 // Timestamp Microseconds (64-bit)
207 "0000000000000000"
208 // Packet Data[0] - HCI_TYPE (8-bit)
209 "02"
210 // Packet Data[1-N] - Data
211 "123456789a";
212 EXPECT_EQ(hex_string_to_bytes(expected_snoop_data), snoop_data);
213 }
214
TEST(SnoopTest,HeaderRxTruncated)215 TEST(SnoopTest, HeaderRxTruncated) {
216 chrono::SimulatedSystemClock clock{};
217 SnoopBuffer<4096, 3> snoop{clock};
218
219 // Add packet 1
220 std::array<uint8_t, 5> rx_data = {0x12, 0x34, 0x56, 0x78, 0x9A};
221 proxy::H4PacketWithHci packet{emboss::H4PacketType::ACL_DATA, rx_data};
222 snoop.AddRx(packet);
223
224 // Get snoop log
225 std::vector<std::byte> snoop_data;
226 Status status = snoop.Dump([&snoop_data](ConstByteSpan data) {
227 for (const std::byte item : data) {
228 snoop_data.push_back(item);
229 }
230 return OkStatus();
231 });
232 EXPECT_TRUE(status.ok());
233
234 // Validate
235 std::string_view expected_snoop_data =
236 ""
237 // Identification Pattern (64-bit)
238 "6274736e6f6f7000"
239 // Version Number (32-bit)
240 "00000001"
241 // Datalink Type (32-bit)
242 "000003ea"
243 // Packet 1
244 // Original Length (32-bit)
245 "00000006"
246 // Included Length (32-bit)
247 "00000004"
248 // Packet Flags (32-bit)
249 "00000001"
250 // Cumulative Drops (32-bit)
251 "00000000"
252 // Timestamp Microseconds (64-bit)
253 "0000000000000000"
254 // Packet Data[0] - HCI_TYPE (8-bit)
255 "02"
256 // Packet Data[1-N] - Data
257 "123456";
258 EXPECT_EQ(hex_string_to_bytes(expected_snoop_data), snoop_data);
259 }
260
TEST(SnoopTest,HeaderTxTx)261 TEST(SnoopTest, HeaderTxTx) {
262 chrono::SimulatedSystemClock clock{};
263 SnoopBuffer<4096, 256> snoop{clock};
264
265 // Add packet 1
266 std::array<uint8_t, 5> tx_data1 = {0x12, 0x34, 0x56, 0x78, 0x9A};
267 proxy::H4PacketWithHci packet1{emboss::H4PacketType::ACL_DATA, tx_data1};
268 snoop.AddTx(packet1);
269
270 // Add packet 2
271 clock.AdvanceTime(pw::chrono::SystemClock::for_at_least(1us));
272 std::array<uint8_t, 3> tx_data2 = {0xBC, 0xDE, 0xF0};
273 proxy::H4PacketWithHci packet2{emboss::H4PacketType::COMMAND, tx_data2};
274 snoop.AddTx(packet2);
275
276 // Get snoop log
277 std::vector<std::byte> snoop_data;
278 Status status = snoop.Dump([&snoop_data](ConstByteSpan data) {
279 for (const std::byte item : data) {
280 snoop_data.push_back(item);
281 }
282 return OkStatus();
283 });
284 EXPECT_TRUE(status.ok());
285
286 // Validate
287 std::string_view expected_snoop_data =
288 ""
289 // Identification Pattern (64-bit)
290 "6274736e6f6f7000"
291 // Version Number (32-bit)
292 "00000001"
293 // Datalink Type (32-bit)
294 "000003ea"
295 // Packet 1
296 // Original Length (32-bit)
297 "00000006"
298 // Included Length (32-bit)
299 "00000006"
300 // Packet Flags (32-bit)
301 "00000000"
302 // Cumulative Drops (32-bit)
303 "00000000"
304 // Timestamp Microseconds (64-bit)
305 "0000000000000000"
306 // Packet Data[0] - HCI_TYPE (8-bit)
307 "02"
308 // Packet Data[1-N] - Data
309 "123456789a"
310 // Packet 2
311 // Original Length (32-bit)
312 "00000004"
313 // Included Length (32-bit)
314 "00000004"
315 // Packet Flags (32-bit)
316 "00000000"
317 // Cumulative Drops (32-bit)
318 "00000000"
319 // Timestamp Microseconds (64-bit)
320 "0000000000000001"
321 // Packet Data[0] - HCI_TYPE (8-bit)
322 "01"
323 // Packet Data[1-N] - Data
324 "BCDEF0";
325 EXPECT_EQ(snoop_data, hex_string_to_bytes(expected_snoop_data));
326 }
327
TEST(SnoopTest,HeaderRxRx)328 TEST(SnoopTest, HeaderRxRx) {
329 chrono::SimulatedSystemClock clock{};
330 SnoopBuffer<4096, 256> snoop{clock};
331
332 // Add packet 1
333 std::array<uint8_t, 5> rx_data1 = {0x12, 0x34, 0x56, 0x78, 0x9A};
334 proxy::H4PacketWithHci packet1{emboss::H4PacketType::ACL_DATA, rx_data1};
335 snoop.AddRx(packet1);
336
337 // Add packet 2
338 clock.AdvanceTime(pw::chrono::SystemClock::for_at_least(1us));
339 std::array<uint8_t, 3> rx_data2 = {0xBC, 0xDE, 0xF0};
340 proxy::H4PacketWithHci packet2{emboss::H4PacketType::COMMAND, rx_data2};
341 snoop.AddRx(packet2);
342
343 // Get snoop log
344 std::vector<std::byte> snoop_data;
345 Status status = snoop.Dump([&snoop_data](ConstByteSpan data) {
346 for (const std::byte item : data) {
347 snoop_data.push_back(item);
348 }
349 return OkStatus();
350 });
351 EXPECT_TRUE(status.ok());
352
353 // Validate
354 std::string_view expected_snoop_data =
355 ""
356 // Identification Pattern (64-bit)
357 "6274736e6f6f7000"
358 // Version Number (32-bit)
359 "00000001"
360 // Datalink Type (32-bit)
361 "000003ea"
362 // Packet 1
363 // Original Length (32-bit)
364 "00000006"
365 // Included Length (32-bit)
366 "00000006"
367 // Packet Flags (32-bit)
368 "00000001"
369 // Cumulative Drops (32-bit)
370 "00000000"
371 // Timestamp Microseconds (64-bit)
372 "0000000000000000"
373 // Packet Data[0] - HCI_TYPE (8-bit)
374 "02"
375 // Packet Data[1-N] - Data
376 "123456789a"
377 // Packet 2
378 // Original Length (32-bit)
379 "00000004"
380 // Included Length (32-bit)
381 "00000004"
382 // Packet Flags (32-bit)
383 "00000001"
384 // Cumulative Drops (32-bit)
385 "00000000"
386 // Timestamp Microseconds (64-bit)
387 "0000000000000001"
388 // Packet Data[0] - HCI_TYPE (8-bit)
389 "01"
390 // Packet Data[1-N] - Data
391 "BCDEF0";
392 EXPECT_EQ(snoop_data, hex_string_to_bytes(expected_snoop_data));
393 }
394
TEST(SnoopTest,HeaderRxTxRxTx)395 TEST(SnoopTest, HeaderRxTxRxTx) {
396 chrono::SimulatedSystemClock clock{};
397 SnoopBuffer<4096, 256> snoop{clock};
398
399 // Add packet 1
400 std::array<uint8_t, 5> rx_data1 = {0x12, 0x34, 0x56, 0x78, 0x9A};
401 proxy::H4PacketWithHci packet1{emboss::H4PacketType::ACL_DATA, rx_data1};
402 snoop.AddRx(packet1);
403
404 // Add packet 2
405 clock.AdvanceTime(pw::chrono::SystemClock::for_at_least(1us));
406 std::array<uint8_t, 3> tx_data1 = {0xBC, 0xDE, 0xF0};
407 proxy::H4PacketWithHci packet2{emboss::H4PacketType::COMMAND, tx_data1};
408 snoop.AddTx(packet2);
409
410 // Add packet 3
411 clock.AdvanceTime(pw::chrono::SystemClock::for_at_least(1us));
412 std::array<uint8_t, 5> rx_data2 = {0x21, 0x43, 0x65, 0x87, 0xA9};
413 proxy::H4PacketWithHci packet3{emboss::H4PacketType::ACL_DATA, rx_data2};
414 snoop.AddRx(packet3);
415
416 // Add packet 4
417 clock.AdvanceTime(pw::chrono::SystemClock::for_at_least(1us));
418 std::array<uint8_t, 3> tx_data2 = {0xCB, 0xED, 0x0F};
419 proxy::H4PacketWithHci packet4{emboss::H4PacketType::COMMAND, tx_data2};
420 snoop.AddTx(packet4);
421
422 // Get snoop log
423 std::vector<std::byte> snoop_data;
424 Status status = snoop.Dump([&snoop_data](ConstByteSpan data) {
425 for (const std::byte item : data) {
426 snoop_data.push_back(item);
427 }
428 return OkStatus();
429 });
430 EXPECT_TRUE(status.ok());
431
432 // Validate
433 std::string_view expected_snoop_data =
434 ""
435 // Identification Pattern (64-bit)
436 "6274736e6f6f7000"
437 // Version Number (32-bit)
438 "00000001"
439 // Datalink Type (32-bit)
440 "000003ea"
441 // Packet 1
442 // Original Length (32-bit)
443 "00000006"
444 // Included Length (32-bit)
445 "00000006"
446 // Packet Flags (32-bit)
447 "00000001"
448 // Cumulative Drops (32-bit)
449 "00000000"
450 // Timestamp Microseconds (64-bit)
451 "0000000000000000"
452 // Packet Data[0] - HCI_TYPE (8-bit)
453 "02"
454 // Packet Data[1-N] - Data
455 "123456789a"
456 // Packet 2
457 // Original Length (32-bit)
458 "00000004"
459 // Included Length (32-bit)
460 "00000004"
461 // Packet Flags (32-bit)
462 "00000000"
463 // Cumulative Drops (32-bit)
464 "00000000"
465 // Timestamp Microseconds (64-bit)
466 "0000000000000001"
467 // Packet Data[0] - HCI_TYPE (8-bit)
468 "01"
469 // Packet Data[1-N] - Data
470 "BCDEF0"
471 // Packet 3
472 // Original Length (32-bit)
473 "00000006"
474 // Included Length (32-bit)
475 "00000006"
476 // Packet Flags (32-bit)
477 "00000001"
478 // Cumulative Drops (32-bit)
479 "00000000"
480 // Timestamp Microseconds (64-bit)
481 "0000000000000002"
482 // Packet Data[0] - HCI_TYPE (8-bit)
483 "02"
484 // Packet Data[1-N] - Data
485 "21436587a9"
486 // Packet 4
487 // Original Length (32-bit)
488 "00000004"
489 // Included Length (32-bit)
490 "00000004"
491 // Packet Flags (32-bit)
492 "00000000"
493 // Cumulative Drops (32-bit)
494 "00000000"
495 // Timestamp Microseconds (64-bit)
496 "0000000000000003"
497 // Packet Data[0] - HCI_TYPE (8-bit)
498 "01"
499 // Packet Data[1-N] - Data
500 "CBED0F";
501 EXPECT_EQ(snoop_data, hex_string_to_bytes(expected_snoop_data));
502 }
503
504 } // namespace
505 } // namespace pw::bluetooth
506