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