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