• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2020 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://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,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include "hal/snoop_logger.h"
18 
19 #include <gmock/gmock.h>
20 #include <gtest/gtest.h>
21 
22 #include "os/fake_timer/fake_timerfd.h"
23 
24 namespace testing {
25 
26 using bluetooth::os::fake_timer::fake_timerfd_advance;
27 using bluetooth::os::fake_timer::fake_timerfd_reset;
28 
29 namespace {
30 std::vector<uint8_t> kInformationRequest = {
31     0xfe,
32     0x2e,
33     0x0a,
34     0x00,
35     0x06,
36     0x00,
37     0x01,
38     0x00,
39     0x0a,
40     0x02,
41     0x02,
42     0x00,
43     0x02,
44     0x00,
45 };
46 
47 std::vector<uint8_t> kSdpConnectionRequest = {
48     0x08, 0x20, 0x0c, 0x00, 0x08, 0x00, 0x01, 0x00, 0x02, 0x0c, 0x04, 0x00, 0x01, 0x00, 0x44, 0x00};
49 
50 std::vector<uint8_t> kAvdtpSuspend = {0x02, 0x02, 0x00, 0x07, 0x00, 0x03, 0x00, 0x8d, 0x00, 0x90, 0x09, 0x04};
51 
52 std::vector<uint8_t> kHfpAtNrec0 = {0x02, 0x02, 0x20, 0x13, 0x00, 0x0f, 0x00, 0x41, 0x00, 0x09, 0xff, 0x15,
53                                     0x01, 0x41, 0x54, 0x2b, 0x4e, 0x52, 0x45, 0x43, 0x3d, 0x30, 0x0d, 0x5c};
54 
55 std::vector<uint8_t> kQualcommConnectionRequest = {0xdc, 0x2e, 0x54, 0x00, 0x50, 0x00, 0xff, 0x00, 0x00, 0x0a,
56                                                    0x0f, 0x09, 0x01, 0x00, 0x5c, 0x93, 0x01, 0x00, 0x42, 0x00};
57 
58 }  // namespace
59 
60 using bluetooth::TestModuleRegistry;
61 using bluetooth::hal::SnoopLogger;
62 using namespace std::chrono_literals;
63 
64 // Expose protected constructor for test
65 class TestSnoopLoggerModule : public SnoopLogger {
66  public:
TestSnoopLoggerModule(std::string snoop_log_path,std::string snooz_log_path,size_t max_packets_per_file,const std::string & btsnoop_mode,bool qualcomm_debug_log_enabled)67   TestSnoopLoggerModule(
68       std::string snoop_log_path,
69       std::string snooz_log_path,
70       size_t max_packets_per_file,
71       const std::string& btsnoop_mode,
72       bool qualcomm_debug_log_enabled)
73       : SnoopLogger(
74             std::move(snoop_log_path),
75             std::move(snooz_log_path),
76             max_packets_per_file,
77             SnoopLogger::GetMaxPacketsPerBuffer(),
78             btsnoop_mode,
79             qualcomm_debug_log_enabled,
80             20ms,
81             5ms) {}
82 
ToString() const83   std::string ToString() const override {
84     return std::string("TestSnoopLoggerModule");
85   }
86 
CallGetDumpsysData(flatbuffers::FlatBufferBuilder * builder)87   void CallGetDumpsysData(flatbuffers::FlatBufferBuilder* builder) {
88     GetDumpsysData(builder);
89   }
90 };
91 
92 class SnoopLoggerModuleTest : public Test {
93  public:
94   flatbuffers::FlatBufferBuilder* builder_;
95 
96  protected:
SetUp()97   void SetUp() override {
98     temp_dir_ = std::filesystem::temp_directory_path();
99     temp_snoop_log_ = temp_dir_ / "btsnoop_hci.log";
100     temp_snoop_log_last_ = temp_dir_ / "btsnoop_hci.log.last";
101     temp_snooz_log_ = temp_dir_ / "btsnooz_hci.log";
102     temp_snooz_log_last_ = temp_dir_ / "btsnooz_hci.log.last";
103     builder_ = new flatbuffers::FlatBufferBuilder();
104 
105     DeleteSnoopLogFiles();
106     ASSERT_FALSE(std::filesystem::exists(temp_snoop_log_));
107     ASSERT_FALSE(std::filesystem::exists(temp_snoop_log_last_));
108     ASSERT_FALSE(std::filesystem::exists(temp_snooz_log_));
109     ASSERT_FALSE(std::filesystem::exists(temp_snooz_log_last_));
110   }
111 
TearDown()112   void TearDown() override {
113     DeleteSnoopLogFiles();
114     delete builder_;
115     fake_timerfd_reset();
116   }
117 
DeleteSnoopLogFiles()118   void DeleteSnoopLogFiles() {
119     if (std::filesystem::exists(temp_snoop_log_)) {
120       ASSERT_TRUE(std::filesystem::remove(temp_snoop_log_));
121     }
122     if (std::filesystem::exists(temp_snoop_log_last_)) {
123       ASSERT_TRUE(std::filesystem::remove(temp_snoop_log_last_));
124     }
125     if (std::filesystem::exists(temp_snooz_log_)) {
126       ASSERT_TRUE(std::filesystem::remove(temp_snooz_log_));
127     }
128     if (std::filesystem::exists(temp_snooz_log_last_)) {
129       ASSERT_TRUE(std::filesystem::remove(temp_snooz_log_last_));
130     }
131   }
132 
133   std::filesystem::path temp_dir_;
134   std::filesystem::path temp_snoop_log_;
135   std::filesystem::path temp_snoop_log_last_;
136   std::filesystem::path temp_snooz_log_;
137   std::filesystem::path temp_snooz_log_last_;
138 };
139 
TEST_F(SnoopLoggerModuleTest,empty_snoop_log_test)140 TEST_F(SnoopLoggerModuleTest, empty_snoop_log_test) {
141   // Actual test
142   auto* snoop_logger = new TestSnoopLoggerModule(
143       temp_snoop_log_.string(), temp_snooz_log_.string(), 10, SnoopLogger::kBtSnoopLogModeFull, false);
144   TestModuleRegistry test_registry;
145   test_registry.InjectTestModule(&SnoopLogger::Factory, snoop_logger);
146   test_registry.StopAll();
147 
148   // Verify states after test
149   ASSERT_TRUE(std::filesystem::exists(temp_snoop_log_));
150   ASSERT_FALSE(std::filesystem::exists(temp_snoop_log_last_));
151   ASSERT_EQ(std::filesystem::file_size(temp_snoop_log_), sizeof(SnoopLogger::FileHeaderType));
152 }
153 
TEST_F(SnoopLoggerModuleTest,disable_snoop_log_test)154 TEST_F(SnoopLoggerModuleTest, disable_snoop_log_test) {
155   // Actual test
156   auto* snoop_logger = new TestSnoopLoggerModule(
157       temp_snoop_log_.string(), temp_snooz_log_.string(), 10, SnoopLogger::kBtSnoopLogModeDisabled, false);
158   TestModuleRegistry test_registry;
159   test_registry.InjectTestModule(&SnoopLogger::Factory, snoop_logger);
160   test_registry.StopAll();
161 
162   // Verify states after test
163   ASSERT_FALSE(std::filesystem::exists(temp_snoop_log_));
164   ASSERT_FALSE(std::filesystem::exists(temp_snoop_log_last_));
165   ASSERT_FALSE(std::filesystem::exists(temp_snooz_log_));
166 }
167 
TEST_F(SnoopLoggerModuleTest,capture_one_packet_test)168 TEST_F(SnoopLoggerModuleTest, capture_one_packet_test) {
169   // Actual test
170   auto* snoop_logger = new TestSnoopLoggerModule(
171       temp_snoop_log_.string(), temp_snooz_log_.string(), 10, SnoopLogger::kBtSnoopLogModeFull, false);
172   TestModuleRegistry test_registry;
173   test_registry.InjectTestModule(&SnoopLogger::Factory, snoop_logger);
174 
175   snoop_logger->Capture(kInformationRequest, SnoopLogger::Direction::OUTGOING, SnoopLogger::PacketType::CMD);
176 
177   test_registry.StopAll();
178 
179   // Verify states after test
180   ASSERT_TRUE(std::filesystem::exists(temp_snoop_log_));
181   ASSERT_FALSE(std::filesystem::exists(temp_snoop_log_last_));
182   ASSERT_EQ(
183       std::filesystem::file_size(temp_snoop_log_),
184       sizeof(SnoopLogger::FileHeaderType) + sizeof(SnoopLogger::PacketHeaderType) + kInformationRequest.size());
185 }
186 
TEST_F(SnoopLoggerModuleTest,capture_hci_cmd_btsnooz_test)187 TEST_F(SnoopLoggerModuleTest, capture_hci_cmd_btsnooz_test) {
188   // Actual test
189   auto* snoop_logger = new TestSnoopLoggerModule(
190       temp_snoop_log_.string(), temp_snooz_log_.string(), 10, SnoopLogger::kBtSnoopLogModeDisabled, false);
191   TestModuleRegistry test_registry;
192   test_registry.InjectTestModule(&SnoopLogger::Factory, snoop_logger);
193 
194   snoop_logger->Capture(kInformationRequest, SnoopLogger::Direction::OUTGOING, SnoopLogger::PacketType::CMD);
195   snoop_logger->CallGetDumpsysData(builder_);
196 
197   ASSERT_TRUE(std::filesystem::exists(temp_snooz_log_));
198   ASSERT_EQ(
199       std::filesystem::file_size(temp_snooz_log_),
200       sizeof(SnoopLogger::FileHeaderType) + sizeof(SnoopLogger::PacketHeaderType) + kInformationRequest.size());
201 
202   test_registry.StopAll();
203 
204   // Verify states after test
205   ASSERT_FALSE(std::filesystem::exists(temp_snoop_log_));
206   ASSERT_FALSE(std::filesystem::exists(temp_snoop_log_last_));
207   ASSERT_FALSE(std::filesystem::exists(temp_snooz_log_));
208 }
209 
TEST_F(SnoopLoggerModuleTest,capture_l2cap_signal_packet_btsnooz_test)210 TEST_F(SnoopLoggerModuleTest, capture_l2cap_signal_packet_btsnooz_test) {
211   // Actual test
212   auto* snoop_logger = new TestSnoopLoggerModule(
213       temp_snoop_log_.string(), temp_snooz_log_.string(), 10, SnoopLogger::kBtSnoopLogModeDisabled, false);
214   TestModuleRegistry test_registry;
215   test_registry.InjectTestModule(&SnoopLogger::Factory, snoop_logger);
216 
217   snoop_logger->Capture(kSdpConnectionRequest, SnoopLogger::Direction::OUTGOING, SnoopLogger::PacketType::ACL);
218   snoop_logger->CallGetDumpsysData(builder_);
219 
220   ASSERT_TRUE(std::filesystem::exists(temp_snooz_log_));
221   ASSERT_EQ(
222       std::filesystem::file_size(temp_snooz_log_),
223       sizeof(SnoopLogger::FileHeaderType) + sizeof(SnoopLogger::PacketHeaderType) + kSdpConnectionRequest.size());
224 
225   test_registry.StopAll();
226 
227   // Verify states after test
228   ASSERT_FALSE(std::filesystem::exists(temp_snoop_log_));
229   ASSERT_FALSE(std::filesystem::exists(temp_snoop_log_last_));
230   ASSERT_FALSE(std::filesystem::exists(temp_snooz_log_));
231 }
232 
TEST_F(SnoopLoggerModuleTest,capture_l2cap_short_data_packet_btsnooz_test)233 TEST_F(SnoopLoggerModuleTest, capture_l2cap_short_data_packet_btsnooz_test) {
234   // Actual test
235   auto* snoop_logger = new TestSnoopLoggerModule(
236       temp_snoop_log_.string(), temp_snooz_log_.string(), 10, SnoopLogger::kBtSnoopLogModeDisabled, false);
237   TestModuleRegistry test_registry;
238   test_registry.InjectTestModule(&SnoopLogger::Factory, snoop_logger);
239 
240   snoop_logger->Capture(kAvdtpSuspend, SnoopLogger::Direction::OUTGOING, SnoopLogger::PacketType::ACL);
241   snoop_logger->CallGetDumpsysData(builder_);
242 
243   ASSERT_TRUE(std::filesystem::exists(temp_snooz_log_));
244   ASSERT_EQ(
245       std::filesystem::file_size(temp_snooz_log_),
246       sizeof(SnoopLogger::FileHeaderType) + sizeof(SnoopLogger::PacketHeaderType) + kAvdtpSuspend.size());
247 
248   test_registry.StopAll();
249 
250   // Verify states after test
251   ASSERT_FALSE(std::filesystem::exists(temp_snoop_log_));
252   ASSERT_FALSE(std::filesystem::exists(temp_snoop_log_last_));
253   ASSERT_FALSE(std::filesystem::exists(temp_snooz_log_));
254 }
255 
TEST_F(SnoopLoggerModuleTest,capture_l2cap_long_data_packet_btsnooz_test)256 TEST_F(SnoopLoggerModuleTest, capture_l2cap_long_data_packet_btsnooz_test) {
257   // Actual test
258   auto* snoop_logger = new TestSnoopLoggerModule(
259       temp_snoop_log_.string(), temp_snooz_log_.string(), 10, SnoopLogger::kBtSnoopLogModeDisabled, false);
260   TestModuleRegistry test_registry;
261   test_registry.InjectTestModule(&SnoopLogger::Factory, snoop_logger);
262 
263   snoop_logger->Capture(kHfpAtNrec0, SnoopLogger::Direction::OUTGOING, SnoopLogger::PacketType::ACL);
264   snoop_logger->CallGetDumpsysData(builder_);
265 
266   ASSERT_TRUE(std::filesystem::exists(temp_snooz_log_));
267   ASSERT_EQ(
268       std::filesystem::file_size(temp_snooz_log_),
269       sizeof(SnoopLogger::FileHeaderType) + sizeof(SnoopLogger::PacketHeaderType) + 14);
270 
271   test_registry.StopAll();
272 
273   // Verify states after test
274   ASSERT_FALSE(std::filesystem::exists(temp_snoop_log_));
275   ASSERT_FALSE(std::filesystem::exists(temp_snoop_log_last_));
276   ASSERT_FALSE(std::filesystem::exists(temp_snooz_log_));
277 }
278 
TEST_F(SnoopLoggerModuleTest,delete_old_snooz_log_files)279 TEST_F(SnoopLoggerModuleTest, delete_old_snooz_log_files) {
280   // Actual test
281   auto* snoop_logger = new TestSnoopLoggerModule(
282       temp_snoop_log_.string(), temp_snooz_log_.string(), 10, SnoopLogger::kBtSnoopLogModeDisabled, false);
283   TestModuleRegistry test_registry;
284   test_registry.InjectTestModule(&SnoopLogger::Factory, snoop_logger);
285 
286   std::filesystem::create_directories(temp_snooz_log_);
287 
288   auto* handler = test_registry.GetTestModuleHandler(&SnoopLogger::Factory);
289   ASSERT_TRUE(std::filesystem::exists(temp_snooz_log_));
290   handler->Post(bluetooth::common::BindOnce(fake_timerfd_advance, 10));
291   ASSERT_TRUE(std::filesystem::exists(temp_snooz_log_));
292   handler->Post(bluetooth::common::BindOnce(fake_timerfd_advance, 15));
293   handler->Post(bluetooth::common::BindOnce(
294       [](std::filesystem::path path) { ASSERT_FALSE(std::filesystem::exists(path)); }, temp_snooz_log_));
295   test_registry.StopAll();
296 }
297 
TEST_F(SnoopLoggerModuleTest,rotate_file_at_new_session_test)298 TEST_F(SnoopLoggerModuleTest, rotate_file_at_new_session_test) {
299   // Start once
300   {
301     auto* snoop_logger = new TestSnoopLoggerModule(
302         temp_snoop_log_.string(), temp_snooz_log_.string(), 10, SnoopLogger::kBtSnoopLogModeFull, false);
303     TestModuleRegistry test_registry;
304     test_registry.InjectTestModule(&SnoopLogger::Factory, snoop_logger);
305     snoop_logger->Capture(kInformationRequest, SnoopLogger::Direction::OUTGOING, SnoopLogger::PacketType::CMD);
306     test_registry.StopAll();
307   }
308 
309   // Verify states after test
310   ASSERT_TRUE(std::filesystem::exists(temp_snoop_log_));
311   ASSERT_FALSE(std::filesystem::exists(temp_snoop_log_last_));
312   ASSERT_EQ(
313       std::filesystem::file_size(temp_snoop_log_),
314       sizeof(SnoopLogger::FileHeaderType) + sizeof(SnoopLogger::PacketHeaderType) + kInformationRequest.size());
315 
316   // Start again
317   {
318     auto* snoop_logger = new TestSnoopLoggerModule(
319         temp_snoop_log_.string(), temp_snooz_log_.string(), 10, SnoopLogger::kBtSnoopLogModeFull, false);
320     TestModuleRegistry test_registry;
321     test_registry.InjectTestModule(&SnoopLogger::Factory, snoop_logger);
322     snoop_logger->Capture(kInformationRequest, SnoopLogger::Direction::OUTGOING, SnoopLogger::PacketType::CMD);
323     snoop_logger->Capture(kInformationRequest, SnoopLogger::Direction::OUTGOING, SnoopLogger::PacketType::CMD);
324     test_registry.StopAll();
325   }
326 
327   // Verify states after test
328   ASSERT_TRUE(std::filesystem::exists(temp_snoop_log_));
329   ASSERT_TRUE(std::filesystem::exists(temp_snoop_log_last_));
330   ASSERT_EQ(
331       std::filesystem::file_size(temp_snoop_log_),
332       sizeof(SnoopLogger::FileHeaderType) + (sizeof(SnoopLogger::PacketHeaderType) + kInformationRequest.size()) * 2);
333   ASSERT_EQ(
334       std::filesystem::file_size(temp_snoop_log_last_),
335       sizeof(SnoopLogger::FileHeaderType) + sizeof(SnoopLogger::PacketHeaderType) + kInformationRequest.size());
336 }
337 
TEST_F(SnoopLoggerModuleTest,rotate_file_after_full_test)338 TEST_F(SnoopLoggerModuleTest, rotate_file_after_full_test) {
339   // Actual test
340   auto* snoop_logger = new TestSnoopLoggerModule(
341       temp_snoop_log_.string(), temp_snooz_log_.string(), 10, SnoopLogger::kBtSnoopLogModeFull, false);
342   TestModuleRegistry test_registry;
343   test_registry.InjectTestModule(&SnoopLogger::Factory, snoop_logger);
344 
345   for (int i = 0; i < 11; i++) {
346     snoop_logger->Capture(kInformationRequest, SnoopLogger::Direction::OUTGOING, SnoopLogger::PacketType::CMD);
347   }
348 
349   test_registry.StopAll();
350 
351   // Verify states after test
352   ASSERT_TRUE(std::filesystem::exists(temp_snoop_log_));
353   ASSERT_TRUE(std::filesystem::exists(temp_snoop_log_last_));
354   ASSERT_EQ(
355       std::filesystem::file_size(temp_snoop_log_),
356       sizeof(SnoopLogger::FileHeaderType) + (sizeof(SnoopLogger::PacketHeaderType) + kInformationRequest.size()) * 1);
357   ASSERT_EQ(
358       std::filesystem::file_size(temp_snoop_log_last_),
359       sizeof(SnoopLogger::FileHeaderType) + (sizeof(SnoopLogger::PacketHeaderType) + kInformationRequest.size()) * 10);
360 }
361 
TEST_F(SnoopLoggerModuleTest,qualcomm_debug_log_test)362 TEST_F(SnoopLoggerModuleTest, qualcomm_debug_log_test) {
363   auto* snoop_logger = new TestSnoopLoggerModule(
364       temp_snoop_log_.string(), temp_snooz_log_.string(), 10, SnoopLogger::kBtSnoopLogModeDisabled, true);
365   TestModuleRegistry test_registry;
366   test_registry.InjectTestModule(&SnoopLogger::Factory, snoop_logger);
367   snoop_logger->Capture(kQualcommConnectionRequest, SnoopLogger::Direction::OUTGOING, SnoopLogger::PacketType::ACL);
368   snoop_logger->CallGetDumpsysData(builder_);
369 
370   ASSERT_TRUE(std::filesystem::exists(temp_snooz_log_));
371   ASSERT_EQ(
372       std::filesystem::file_size(temp_snooz_log_),
373       sizeof(SnoopLogger::FileHeaderType) + sizeof(SnoopLogger::PacketHeaderType) + kQualcommConnectionRequest.size());
374 
375   test_registry.StopAll();
376 
377   // Verify states after test
378   ASSERT_FALSE(std::filesystem::exists(temp_snoop_log_));
379   ASSERT_FALSE(std::filesystem::exists(temp_snoop_log_last_));
380   ASSERT_FALSE(std::filesystem::exists(temp_snooz_log_));
381 }
382 
TEST_F(SnoopLoggerModuleTest,qualcomm_debug_log_regression_test)383 TEST_F(SnoopLoggerModuleTest, qualcomm_debug_log_regression_test) {
384   {
385     auto* snoop_logger = new TestSnoopLoggerModule(
386         temp_snoop_log_.string(), temp_snooz_log_.string(), 10, SnoopLogger::kBtSnoopLogModeDisabled, true);
387     TestModuleRegistry test_registry;
388     test_registry.InjectTestModule(&SnoopLogger::Factory, snoop_logger);
389     snoop_logger->Capture(kHfpAtNrec0, SnoopLogger::Direction::OUTGOING, SnoopLogger::PacketType::ACL);
390     snoop_logger->CallGetDumpsysData(builder_);
391 
392     ASSERT_TRUE(std::filesystem::exists(temp_snooz_log_));
393     ASSERT_EQ(
394         std::filesystem::file_size(temp_snooz_log_),
395         sizeof(SnoopLogger::FileHeaderType) + sizeof(SnoopLogger::PacketHeaderType) + 14);
396     test_registry.StopAll();
397   }
398 
399   // Verify states after test
400   ASSERT_FALSE(std::filesystem::exists(temp_snoop_log_));
401   ASSERT_FALSE(std::filesystem::exists(temp_snoop_log_last_));
402   ASSERT_FALSE(std::filesystem::exists(temp_snooz_log_));
403 
404   {
405     auto* snoop_logger = new TestSnoopLoggerModule(
406         temp_snoop_log_.string(), temp_snooz_log_.string(), 10, SnoopLogger::kBtSnoopLogModeDisabled, false);
407     TestModuleRegistry test_registry;
408     test_registry.InjectTestModule(&SnoopLogger::Factory, snoop_logger);
409     snoop_logger->Capture(kQualcommConnectionRequest, SnoopLogger::Direction::OUTGOING, SnoopLogger::PacketType::ACL);
410     snoop_logger->CallGetDumpsysData(builder_);
411 
412     ASSERT_TRUE(std::filesystem::exists(temp_snooz_log_));
413     ASSERT_EQ(
414         std::filesystem::file_size(temp_snooz_log_),
415         sizeof(SnoopLogger::FileHeaderType) + sizeof(SnoopLogger::PacketHeaderType) + 14);
416     test_registry.StopAll();
417   }
418 
419   // Verify states after test
420   ASSERT_FALSE(std::filesystem::exists(temp_snoop_log_));
421   ASSERT_FALSE(std::filesystem::exists(temp_snoop_log_last_));
422   ASSERT_FALSE(std::filesystem::exists(temp_snooz_log_));
423 }
424 
425 }  // namespace testing
426