blob: f0c49b5782c970098fc94a44286722f0d7698838 [file] [log] [blame]
Myles Watsone4501e52022-09-30 06:20:50 -07001/*
2 * Copyright 2022 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#define LOG_TAG "bt_h4_unittest"
18
19#include "h4_protocol.h"
20
21#include <gmock/gmock.h>
22#include <gtest/gtest.h>
23#include <log/log.h>
24#include <sys/socket.h>
25#include <sys/types.h>
26#include <unistd.h>
27
28#include <cstdint>
29#include <cstring>
30#include <future>
31#include <vector>
32
33#include "async_fd_watcher.h"
Myles Watsone4501e52022-09-30 06:20:50 -070034
35using android::hardware::bluetooth::async::AsyncFdWatcher;
36using namespace android::hardware::bluetooth::hci;
37using ::testing::Eq;
38
39static char sample_data1[100] = "A point is that which has no part.";
40static char sample_data2[100] = "A line is breadthless length.";
41static char sample_data3[100] = "The ends of a line are points.";
42static char sample_data4[100] =
43 "A plane surface is a surface which lies evenly with the straight ...";
44static char acl_data[100] =
45 "A straight line is a line which lies evenly with the points on itself.";
46static char sco_data[100] =
47 "A surface is that which has length and breadth only.";
48static char event_data[100] = "The edges of a surface are lines.";
49static char iso_data[100] =
50 "A plane angle is the inclination to one another of two lines in a ...";
Myles Watsonbcc997b2023-04-21 09:38:03 -070051static char short_payload[10] = "12345";
Myles Watsone4501e52022-09-30 06:20:50 -070052
Myles Watsonf99027f2023-02-09 09:30:52 -080053// 5 seconds. Just don't hang.
54static constexpr size_t kTimeoutMs = 5000;
55
Myles Watsone4501e52022-09-30 06:20:50 -070056MATCHER_P3(PacketMatches, header_, header_length, payload,
57 "Match header_length bytes of header and then the payload") {
58 size_t payload_length = strlen(payload);
59 if (header_length + payload_length != arg.size()) {
60 return false;
61 }
62
63 if (memcmp(header_, arg.data(), header_length) != 0) {
64 return false;
65 }
66
67 return memcmp(payload, arg.data() + header_length, payload_length) == 0;
68};
69
70ACTION_P(Notify, barrier) {
71 ALOGD("%s", __func__);
72 barrier->set_value();
73}
74
75class H4ProtocolTest : public ::testing::Test {
76 protected:
77 void SetUp() override {
78 ALOGD("%s", __func__);
79
80 int sockfd[2];
81 socketpair(AF_LOCAL, SOCK_STREAM, 0, sockfd);
82 chip_uart_fd_ = sockfd[1];
83 stack_uart_fd_ = sockfd[0];
84 h4_hci_ = std::make_shared<H4Protocol>(
85 stack_uart_fd_, cmd_cb_.AsStdFunction(), acl_cb_.AsStdFunction(),
86 sco_cb_.AsStdFunction(), event_cb_.AsStdFunction(),
87 iso_cb_.AsStdFunction(), disconnect_cb_.AsStdFunction());
88 }
89
90 void TearDown() override {
91 close(stack_uart_fd_);
92 close(chip_uart_fd_);
93 }
94
95 virtual void CallDataReady() { h4_hci_->OnDataReady(); }
96
97 void SendAndReadUartOutbound(PacketType type, char* data) {
98 ALOGD("%s sending", __func__);
99 int data_length = strlen(data);
100 h4_hci_->Send(type, (uint8_t*)data, data_length);
101
102 int uart_length = data_length + 1; // + 1 for data type code
103 int i;
104
105 ALOGD("%s reading", __func__);
106 for (i = 0; i < uart_length; i++) {
107 fd_set read_fds;
108 FD_ZERO(&read_fds);
109 FD_SET(chip_uart_fd_, &read_fds);
110 TEMP_FAILURE_RETRY(
111 select(chip_uart_fd_ + 1, &read_fds, nullptr, nullptr, nullptr));
112
113 char byte;
114 TEMP_FAILURE_RETRY(read(chip_uart_fd_, &byte, 1));
115
116 EXPECT_EQ(i == 0 ? static_cast<uint8_t>(type) : data[i - 1], byte);
117 }
118
119 EXPECT_EQ(i, uart_length);
120 }
121
122 void ExpectInboundAclData(char* payload, std::promise<void>* promise) {
123 // h4 type[1] + handle[2] + size[2]
124 header_[0] = static_cast<uint8_t>(PacketType::ACL_DATA);
125 header_[1] = 19;
126 header_[2] = 92;
127 int length = strlen(payload);
128 header_[3] = length & 0xFF;
129 header_[4] = (length >> 8) & 0xFF;
130 ALOGD("(%d bytes) %s", length, payload);
131
132 EXPECT_CALL(acl_cb_,
133 Call(PacketMatches(header_ + 1, kAclHeaderSize, payload)))
134 .WillOnce(Notify(promise));
135 }
136
Myles Watsonf99027f2023-02-09 09:30:52 -0800137 void WaitForTimeout(std::promise<void>* promise) {
Myles Watsone4501e52022-09-30 06:20:50 -0700138 auto future = promise->get_future();
Myles Watsonf99027f2023-02-09 09:30:52 -0800139 auto status = future.wait_for(std::chrono::milliseconds(kTimeoutMs));
Myles Watsone4501e52022-09-30 06:20:50 -0700140 EXPECT_EQ(status, std::future_status::ready);
141 }
142
143 void WriteInboundAclData(char* payload) {
144 // Use the header_ computed in ExpectInboundAclData
145 TEMP_FAILURE_RETRY(write(chip_uart_fd_, header_, kAclHeaderSize + 1));
146 TEMP_FAILURE_RETRY(write(chip_uart_fd_, payload, strlen(payload)));
147 }
148
149 void ExpectInboundScoData(char* payload, std::promise<void>* promise) {
150 // h4 type[1] + handle[2] + size[1]
151 header_[0] = static_cast<uint8_t>(PacketType::SCO_DATA);
152 header_[1] = 20;
153 header_[2] = 17;
154 header_[3] = strlen(payload) & 0xFF;
155 EXPECT_CALL(sco_cb_,
156 Call(PacketMatches(header_ + 1, kScoHeaderSize, payload)))
157 .WillOnce(Notify(promise));
158 }
159
160 void WriteInboundScoData(char* payload) {
161 // Use the header_ computed in ExpectInboundScoData
162 ALOGD("%s writing", __func__);
163 TEMP_FAILURE_RETRY(write(chip_uart_fd_, header_, kScoHeaderSize + 1));
164 TEMP_FAILURE_RETRY(write(chip_uart_fd_, payload, strlen(payload)));
165 }
166
167 void ExpectInboundEvent(char* payload, std::promise<void>* promise) {
168 // h4 type[1] + event_code[1] + size[1]
169 header_[0] = static_cast<uint8_t>(PacketType::EVENT);
170 header_[1] = 9;
171 header_[2] = strlen(payload) & 0xFF;
172 EXPECT_CALL(event_cb_,
173 Call(PacketMatches(header_ + 1, kEventHeaderSize, payload)))
174 .WillOnce(Notify(promise));
175 }
176
177 void WriteInboundEvent(char* payload) {
178 // Use the header_ computed in ExpectInboundEvent
179 char preamble[3] = {static_cast<uint8_t>(PacketType::EVENT), 9, 0};
180 preamble[2] = strlen(payload) & 0xFF;
181 ALOGD("%s writing", __func__);
182 TEMP_FAILURE_RETRY(write(chip_uart_fd_, header_, kEventHeaderSize + 1));
183 TEMP_FAILURE_RETRY(write(chip_uart_fd_, payload, strlen(payload)));
184 }
185
186 void ExpectInboundIsoData(char* payload, std::promise<void>* promise) {
187 // h4 type[1] + handle[2] + size[1]
188 header_[0] = static_cast<uint8_t>(PacketType::ISO_DATA);
189 header_[1] = 19;
190 header_[2] = 92;
191 int length = strlen(payload);
192 header_[3] = length & 0xFF;
193 header_[4] = (length >> 8) & 0x3F;
194
195 EXPECT_CALL(iso_cb_,
196 Call(PacketMatches(header_ + 1, kIsoHeaderSize, payload)))
197 .WillOnce(Notify(promise));
198 }
199
200 void WriteInboundIsoData(char* payload) {
201 // Use the header_ computed in ExpectInboundIsoData
202 ALOGD("%s writing", __func__);
203 TEMP_FAILURE_RETRY(write(chip_uart_fd_, header_, kIsoHeaderSize + 1));
204 TEMP_FAILURE_RETRY(write(chip_uart_fd_, payload, strlen(payload)));
205 }
206
207 void WriteAndExpectManyInboundAclDataPackets(char* payload) {
208 size_t kNumPackets = 20;
209 // h4 type[1] + handle[2] + size[2]
210 char preamble[5] = {static_cast<uint8_t>(PacketType::ACL_DATA), 19, 92, 0,
211 0};
212 int length = strlen(payload);
213 preamble[3] = length & 0xFF;
214 preamble[4] = (length >> 8) & 0xFF;
215
216 EXPECT_CALL(acl_cb_, Call(PacketMatches(preamble + 1, sizeof(preamble) - 1,
217 payload)))
218 .Times(kNumPackets);
219
220 for (size_t i = 0; i < kNumPackets; i++) {
221 TEMP_FAILURE_RETRY(write(chip_uart_fd_, preamble, sizeof(preamble)));
222 TEMP_FAILURE_RETRY(write(chip_uart_fd_, payload, strlen(payload)));
223 }
224
225 CallDataReady();
226 }
227
Myles Watsonbcc997b2023-04-21 09:38:03 -0700228 void WriteAndExpectManyAclDataPacketsDifferentOffsetsShort() {
229 std::promise<void> last_packet_promise;
230 size_t kNumPackets = 30;
231 // h4 type[1] + handle[2] + size[2]
232 char preamble[5] = {static_cast<uint8_t>(PacketType::ACL_DATA), 19, 92, 0,
233 0};
234 int length = strlen(short_payload);
235 preamble[3] = length & 0xFF;
236 preamble[4] = 0;
237
238 EXPECT_CALL(acl_cb_, Call(PacketMatches(preamble + 1, kAclHeaderSize,
239 short_payload)))
240 .Times(kNumPackets);
241 ExpectInboundEvent(event_data, &last_packet_promise);
242
243 char all_packets[kNumPackets * 10];
244 size_t total_bytes = 0;
245
246 for (size_t packet = 0; packet < kNumPackets; packet++) {
247 for (size_t i = 0; i < sizeof(preamble); i++) {
248 all_packets[total_bytes++] = preamble[i];
249 }
250 for (size_t i = 0; i < length; i++) {
251 all_packets[total_bytes++] = short_payload[i];
252 }
253 }
254
255 size_t written_bytes = 0;
256 size_t partial_size = 1;
257 while (written_bytes < total_bytes) {
258 size_t to_write = std::min(partial_size, total_bytes - written_bytes);
259 TEMP_FAILURE_RETRY(
260 write(chip_uart_fd_, all_packets + written_bytes, to_write));
261 written_bytes += to_write;
262 CallDataReady();
263 partial_size++;
264 partial_size = partial_size % 5 + 1;
265 }
266 WriteInboundEvent(event_data);
267 CallDataReady();
268 WaitForTimeout(&last_packet_promise);
269 }
270
Myles Watsone4501e52022-09-30 06:20:50 -0700271 testing::MockFunction<void(const std::vector<uint8_t>&)> cmd_cb_;
272 testing::MockFunction<void(const std::vector<uint8_t>&)> event_cb_;
273 testing::MockFunction<void(const std::vector<uint8_t>&)> acl_cb_;
274 testing::MockFunction<void(const std::vector<uint8_t>&)> sco_cb_;
275 testing::MockFunction<void(const std::vector<uint8_t>&)> iso_cb_;
276 testing::MockFunction<void(void)> disconnect_cb_;
277 std::shared_ptr<H4Protocol> h4_hci_;
278 int chip_uart_fd_;
279 int stack_uart_fd_;
280
281 char header_[5];
282};
283
284// Test sending data sends correct data onto the UART
285TEST_F(H4ProtocolTest, TestSends) {
286 SendAndReadUartOutbound(PacketType::COMMAND, sample_data1);
287 SendAndReadUartOutbound(PacketType::ACL_DATA, sample_data2);
288 SendAndReadUartOutbound(PacketType::SCO_DATA, sample_data3);
289 SendAndReadUartOutbound(PacketType::ISO_DATA, sample_data4);
290}
291
292// Ensure we properly parse data coming from the UART
293TEST_F(H4ProtocolTest, TestReads) {
294 std::promise<void> acl_promise;
295 std::promise<void> sco_promise;
296 std::promise<void> event_promise;
297 std::promise<void> iso_promise;
298
299 ExpectInboundAclData(acl_data, &acl_promise);
300 WriteInboundAclData(acl_data);
301 CallDataReady();
302 ExpectInboundScoData(sco_data, &sco_promise);
303 WriteInboundScoData(sco_data);
304 CallDataReady();
305 ExpectInboundEvent(event_data, &event_promise);
306 WriteInboundEvent(event_data);
307 CallDataReady();
308 ExpectInboundIsoData(iso_data, &iso_promise);
309 WriteInboundIsoData(iso_data);
310 CallDataReady();
311
Myles Watsonf99027f2023-02-09 09:30:52 -0800312 WaitForTimeout(&acl_promise);
313 WaitForTimeout(&sco_promise);
314 WaitForTimeout(&event_promise);
315 WaitForTimeout(&iso_promise);
Myles Watsone4501e52022-09-30 06:20:50 -0700316}
317
318TEST_F(H4ProtocolTest, TestMultiplePackets) {
319 WriteAndExpectManyInboundAclDataPackets(sco_data);
320}
321
Myles Watsonbcc997b2023-04-21 09:38:03 -0700322TEST_F(H4ProtocolTest, TestMultipleWritesPacketsShortWrites) {
323 WriteAndExpectManyAclDataPacketsDifferentOffsetsShort();
324}
325
Myles Watsone4501e52022-09-30 06:20:50 -0700326TEST_F(H4ProtocolTest, TestDisconnect) {
327 EXPECT_CALL(disconnect_cb_, Call());
328 close(chip_uart_fd_);
329 CallDataReady();
330}
331
332TEST_F(H4ProtocolTest, TestPartialWrites) {
333 size_t payload_len = strlen(acl_data);
334 const size_t kNumIntervals = payload_len + 1;
335 // h4 type[1] + handle[2] + size[2]
336 header_[0] = static_cast<uint8_t>(PacketType::ACL_DATA);
337 header_[1] = 19;
338 header_[2] = 92;
339 header_[3] = payload_len & 0xFF;
340 header_[4] = (payload_len >> 8) & 0xFF;
341
342 EXPECT_CALL(acl_cb_,
343 Call(PacketMatches(header_ + 1, sizeof(header_) - 1, acl_data)))
344 .Times(kNumIntervals);
345
346 for (size_t interval = 1; interval < kNumIntervals + 1; interval++) {
347 // Use the header_ data that expect already set up.
348 if (interval < kAclHeaderSize) {
349 TEMP_FAILURE_RETRY(write(chip_uart_fd_, header_, interval));
350 CallDataReady();
351 TEMP_FAILURE_RETRY(write(chip_uart_fd_, header_ + interval,
352 kAclHeaderSize + 1 - interval));
353 CallDataReady();
354 } else {
355 TEMP_FAILURE_RETRY(write(chip_uart_fd_, header_, kAclHeaderSize + 1));
356 CallDataReady();
357 }
358
359 for (size_t bytes = 0; bytes + interval <= payload_len; bytes += interval) {
360 TEMP_FAILURE_RETRY(write(chip_uart_fd_, acl_data + bytes, interval));
361 CallDataReady();
362 }
363 size_t extra_bytes = payload_len % interval;
364 if (extra_bytes) {
365 TEMP_FAILURE_RETRY(write(
366 chip_uart_fd_, acl_data + payload_len - extra_bytes, extra_bytes));
367 CallDataReady();
368 }
369 }
370}
371
372class H4ProtocolAsyncTest : public H4ProtocolTest {
373 protected:
374 void SetUp() override {
375 H4ProtocolTest::SetUp();
376 fd_watcher_.WatchFdForNonBlockingReads(
377 stack_uart_fd_, [this](int) { h4_hci_->OnDataReady(); });
378 }
379
380 void TearDown() override { fd_watcher_.StopWatchingFileDescriptors(); }
381
Myles Watsonbcc997b2023-04-21 09:38:03 -0700382 // Calling CallDataReady() has no effect in the AsyncTest
383 void CallDataReady() override {}
Myles Watsone4501e52022-09-30 06:20:50 -0700384
385 void SendAndReadUartOutbound(PacketType type, char* data) {
386 ALOGD("%s sending", __func__);
387 int data_length = strlen(data);
388 h4_hci_->Send(type, (uint8_t*)data, data_length);
389
390 int uart_length = data_length + 1; // + 1 for data type code
391 int i;
392
393 ALOGD("%s reading", __func__);
394 for (i = 0; i < uart_length; i++) {
395 fd_set read_fds;
396 FD_ZERO(&read_fds);
397 FD_SET(chip_uart_fd_, &read_fds);
398 TEMP_FAILURE_RETRY(
399 select(chip_uart_fd_ + 1, &read_fds, nullptr, nullptr, nullptr));
400
401 char byte;
402 TEMP_FAILURE_RETRY(read(chip_uart_fd_, &byte, 1));
403
404 EXPECT_EQ(i == 0 ? static_cast<uint8_t>(type) : data[i - 1], byte);
405 }
406
407 EXPECT_EQ(i, uart_length);
408 }
409
410 void WriteAndExpectInboundAclData(char* payload) {
411 std::promise<void> promise;
412 ExpectInboundAclData(payload, &promise);
413 WriteInboundAclData(payload);
Myles Watsonf99027f2023-02-09 09:30:52 -0800414 WaitForTimeout(&promise);
Myles Watsone4501e52022-09-30 06:20:50 -0700415 }
416
417 void WriteAndExpectInboundScoData(char* payload) {
418 std::promise<void> promise;
419 ExpectInboundScoData(payload, &promise);
420 WriteInboundScoData(payload);
Myles Watsonf99027f2023-02-09 09:30:52 -0800421 WaitForTimeout(&promise);
Myles Watsone4501e52022-09-30 06:20:50 -0700422 }
423
424 void WriteAndExpectInboundEvent(char* payload) {
425 std::promise<void> promise;
426 ExpectInboundEvent(payload, &promise);
427 WriteInboundEvent(payload);
Myles Watsonf99027f2023-02-09 09:30:52 -0800428 WaitForTimeout(&promise);
Myles Watsone4501e52022-09-30 06:20:50 -0700429 }
430
431 void WriteAndExpectInboundIsoData(char* payload) {
432 std::promise<void> promise;
433 ExpectInboundIsoData(payload, &promise);
434 WriteInboundIsoData(payload);
Myles Watsonf99027f2023-02-09 09:30:52 -0800435 WaitForTimeout(&promise);
Myles Watsone4501e52022-09-30 06:20:50 -0700436 }
437
438 void WriteAndExpectManyInboundAclDataPackets(char* payload) {
439 const size_t kNumPackets = 20;
440 // h4 type[1] + handle[2] + size[2]
441 char preamble[5] = {static_cast<uint8_t>(PacketType::ACL_DATA), 19, 92, 0,
442 0};
443 int length = strlen(payload);
444 preamble[3] = length & 0xFF;
445 preamble[4] = (length >> 8) & 0xFF;
446
447 EXPECT_CALL(acl_cb_, Call(PacketMatches(preamble + 1, sizeof(preamble) - 1,
448 payload)))
449 .Times(kNumPackets);
450
451 for (size_t i = 0; i < kNumPackets; i++) {
452 TEMP_FAILURE_RETRY(write(chip_uart_fd_, preamble, sizeof(preamble)));
453 TEMP_FAILURE_RETRY(write(chip_uart_fd_, payload, strlen(payload)));
454 }
455
456 WriteAndExpectInboundEvent(event_data);
457 }
458
459 AsyncFdWatcher fd_watcher_;
460};
461
462// Test sending data sends correct data onto the UART
463TEST_F(H4ProtocolAsyncTest, TestSends) {
464 SendAndReadUartOutbound(PacketType::COMMAND, sample_data1);
465 SendAndReadUartOutbound(PacketType::ACL_DATA, sample_data2);
466 SendAndReadUartOutbound(PacketType::SCO_DATA, sample_data3);
467 SendAndReadUartOutbound(PacketType::ISO_DATA, sample_data4);
468}
469
470// Ensure we properly parse data coming from the UART
471TEST_F(H4ProtocolAsyncTest, TestReads) {
472 WriteAndExpectInboundAclData(acl_data);
473 WriteAndExpectInboundScoData(sco_data);
474 WriteAndExpectInboundEvent(event_data);
475 WriteAndExpectInboundIsoData(iso_data);
476}
477
478TEST_F(H4ProtocolAsyncTest, TestMultiplePackets) {
479 WriteAndExpectManyInboundAclDataPackets(sco_data);
480}
481
Myles Watsonbcc997b2023-04-21 09:38:03 -0700482TEST_F(H4ProtocolAsyncTest, TestMultipleWritesPacketsShortWrites) {
483 WriteAndExpectManyAclDataPacketsDifferentOffsetsShort();
484}
485
Myles Watsone4501e52022-09-30 06:20:50 -0700486TEST_F(H4ProtocolAsyncTest, TestDisconnect) {
487 std::promise<void> promise;
488 EXPECT_CALL(disconnect_cb_, Call()).WillOnce(Notify(&promise));
489 close(chip_uart_fd_);
490
Myles Watsonf99027f2023-02-09 09:30:52 -0800491 WaitForTimeout(&promise);
Myles Watsone4501e52022-09-30 06:20:50 -0700492}