1 //
2 // Copyright 2017 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 #include <gmock/gmock.h>
21 #include <gtest/gtest.h>
22 #include <condition_variable>
23 #include <cstdint>
24 #include <cstring>
25 #include <mutex>
26 #include <vector>
27
28 #include <log/log.h>
29 #include <sys/socket.h>
30 #include <sys/types.h>
31 #include <unistd.h>
32
33 namespace android {
34 namespace hardware {
35 namespace bluetooth {
36 namespace V1_0 {
37 namespace implementation {
38
39 using ::testing::Eq;
40 using hci::H4Protocol;
41
42 static char sample_data1[100] = "A point is that which has no part.";
43 static char sample_data2[100] = "A line is breadthless length.";
44 static char sample_data3[100] = "The ends of a line are points.";
45 static char acl_data[100] =
46 "A straight line is a line which lies evenly with the points on itself.";
47 static char sco_data[100] =
48 "A surface is that which has length and breadth only.";
49 static char event_data[100] = "The edges of a surface are lines.";
50
51 MATCHER_P3(HidlVecMatches, preamble, preamble_length, payload, "") {
52 size_t length = strlen(payload) + preamble_length;
53 if (length != arg.size()) {
54 return false;
55 }
56
57 if (memcmp(preamble, arg.data(), preamble_length) != 0) {
58 return false;
59 }
60
61 return memcmp(payload, arg.data() + preamble_length,
62 length - preamble_length) == 0;
63 };
64
ACTION_P2(Notify,mutex,condition)65 ACTION_P2(Notify, mutex, condition) {
66 ALOGD("%s", __func__);
67 std::unique_lock<std::mutex> lock(*mutex);
68 condition->notify_one();
69 }
70
71 class H4ProtocolTest : public ::testing::Test {
72 protected:
SetUp()73 void SetUp() override {
74 ALOGD("%s", __func__);
75
76 int sockfd[2];
77 socketpair(AF_LOCAL, SOCK_STREAM, 0, sockfd);
78 H4Protocol* h4_hci =
79 new H4Protocol(sockfd[0], event_cb_.AsStdFunction(),
80 acl_cb_.AsStdFunction(), sco_cb_.AsStdFunction());
81 fd_watcher_.WatchFdForNonBlockingReads(
82 sockfd[0], [h4_hci](int fd) { h4_hci->OnDataReady(fd); });
83 protocol_ = h4_hci;
84
85 fake_uart_ = sockfd[1];
86 }
87
TearDown()88 void TearDown() override { fd_watcher_.StopWatchingFileDescriptors(); }
89
SendAndReadUartOutbound(uint8_t type,char * data)90 void SendAndReadUartOutbound(uint8_t type, char* data) {
91 ALOGD("%s sending", __func__);
92 int data_length = strlen(data);
93 protocol_->Send(type, (uint8_t*)data, data_length);
94
95 int uart_length = data_length + 1; // + 1 for data type code
96 int i;
97
98 ALOGD("%s reading", __func__);
99 for (i = 0; i < uart_length; i++) {
100 fd_set read_fds;
101 FD_ZERO(&read_fds);
102 FD_SET(fake_uart_, &read_fds);
103 TEMP_FAILURE_RETRY(select(fake_uart_ + 1, &read_fds, NULL, NULL, NULL));
104
105 char byte;
106 TEMP_FAILURE_RETRY(read(fake_uart_, &byte, 1));
107
108 EXPECT_EQ(i == 0 ? type : data[i - 1], byte);
109 }
110
111 EXPECT_EQ(i, uart_length);
112 }
113
WriteAndExpectInboundAclData(char * payload)114 void WriteAndExpectInboundAclData(char* payload) {
115 // h4 type[1] + handle[2] + size[2]
116 char preamble[5] = {HCI_PACKET_TYPE_ACL_DATA, 19, 92, 0, 0};
117 int length = strlen(payload);
118 preamble[3] = length & 0xFF;
119 preamble[4] = (length >> 8) & 0xFF;
120
121 ALOGD("%s writing", __func__);
122 TEMP_FAILURE_RETRY(write(fake_uart_, preamble, sizeof(preamble)));
123 TEMP_FAILURE_RETRY(write(fake_uart_, payload, strlen(payload)));
124
125 ALOGD("%s waiting", __func__);
126 std::mutex mutex;
127 std::condition_variable done;
128 EXPECT_CALL(acl_cb_, Call(HidlVecMatches(preamble + 1, sizeof(preamble) - 1,
129 payload)))
130 .WillOnce(Notify(&mutex, &done));
131
132 // Fail if it takes longer than 100 ms.
133 auto timeout_time =
134 std::chrono::steady_clock::now() + std::chrono::milliseconds(100);
135 {
136 std::unique_lock<std::mutex> lock(mutex);
137 done.wait_until(lock, timeout_time);
138 }
139 }
140
WriteAndExpectInboundScoData(char * payload)141 void WriteAndExpectInboundScoData(char* payload) {
142 // h4 type[1] + handle[2] + size[1]
143 char preamble[4] = {HCI_PACKET_TYPE_SCO_DATA, 20, 17, 0};
144 preamble[3] = strlen(payload) & 0xFF;
145
146 ALOGD("%s writing", __func__);
147 TEMP_FAILURE_RETRY(write(fake_uart_, preamble, sizeof(preamble)));
148 TEMP_FAILURE_RETRY(write(fake_uart_, payload, strlen(payload)));
149
150 ALOGD("%s waiting", __func__);
151 std::mutex mutex;
152 std::condition_variable done;
153 EXPECT_CALL(sco_cb_, Call(HidlVecMatches(preamble + 1, sizeof(preamble) - 1,
154 payload)))
155 .WillOnce(Notify(&mutex, &done));
156
157 // Fail if it takes longer than 100 ms.
158 auto timeout_time =
159 std::chrono::steady_clock::now() + std::chrono::milliseconds(100);
160 {
161 std::unique_lock<std::mutex> lock(mutex);
162 done.wait_until(lock, timeout_time);
163 }
164 }
165
WriteAndExpectInboundEvent(char * payload)166 void WriteAndExpectInboundEvent(char* payload) {
167 // h4 type[1] + event_code[1] + size[1]
168 char preamble[3] = {HCI_PACKET_TYPE_EVENT, 9, 0};
169 preamble[2] = strlen(payload) & 0xFF;
170 ALOGD("%s writing", __func__);
171 TEMP_FAILURE_RETRY(write(fake_uart_, preamble, sizeof(preamble)));
172 TEMP_FAILURE_RETRY(write(fake_uart_, payload, strlen(payload)));
173
174 ALOGD("%s waiting", __func__);
175 std::mutex mutex;
176 std::condition_variable done;
177 EXPECT_CALL(event_cb_, Call(HidlVecMatches(preamble + 1,
178 sizeof(preamble) - 1, payload)))
179 .WillOnce(Notify(&mutex, &done));
180
181 {
182 std::unique_lock<std::mutex> lock(mutex);
183 done.wait(lock);
184 }
185 }
186
187 testing::MockFunction<void(const hidl_vec<uint8_t>&)> event_cb_;
188 testing::MockFunction<void(const hidl_vec<uint8_t>&)> acl_cb_;
189 testing::MockFunction<void(const hidl_vec<uint8_t>&)> sco_cb_;
190 async::AsyncFdWatcher fd_watcher_;
191 H4Protocol* protocol_;
192 int fake_uart_;
193 };
194
195 // Test sending data sends correct data onto the UART
TEST_F(H4ProtocolTest,TestSends)196 TEST_F(H4ProtocolTest, TestSends) {
197 SendAndReadUartOutbound(HCI_PACKET_TYPE_COMMAND, sample_data1);
198 SendAndReadUartOutbound(HCI_PACKET_TYPE_ACL_DATA, sample_data2);
199 SendAndReadUartOutbound(HCI_PACKET_TYPE_SCO_DATA, sample_data3);
200 }
201
202 // Ensure we properly parse data coming from the UART
TEST_F(H4ProtocolTest,TestReads)203 TEST_F(H4ProtocolTest, TestReads) {
204 WriteAndExpectInboundAclData(acl_data);
205 WriteAndExpectInboundScoData(sco_data);
206 WriteAndExpectInboundEvent(event_data);
207 }
208
209 } // namespace implementation
210 } // namespace V1_0
211 } // namespace bluetooth
212 } // namespace hardware
213 } // namespace android
214