• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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