• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "mct_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::MctProtocol;
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 acl_data[100] =
45     "A straight line is a line which lies evenly with the points on itself.";
46 static char event_data[100] = "The edges of a surface are lines.";
47 
48 MATCHER_P3(HidlVecMatches, preamble, preamble_length, payload, "") {
49   size_t length = strlen(payload) + preamble_length;
50   if (length != arg.size()) {
51     return false;
52   }
53 
54   if (memcmp(preamble, arg.data(), preamble_length) != 0) {
55     return false;
56   }
57 
58   return memcmp(payload, arg.data() + preamble_length,
59                 length - preamble_length) == 0;
60 };
61 
ACTION_P2(Notify,mutex,condition)62 ACTION_P2(Notify, mutex, condition) {
63   ALOGD("%s", __func__);
64   std::unique_lock<std::mutex> lock(*mutex);
65   condition->notify_one();
66 }
67 
68 class MctProtocolTest : public ::testing::Test {
69  protected:
SetUp()70   void SetUp() override {
71     ALOGD("%s", __func__);
72 
73     int mct_fds[CH_MAX];
74     MakeFakeUartFd(CH_CMD, mct_fds, fake_uart_);
75     MakeFakeUartFd(CH_EVT, mct_fds, fake_uart_);
76     MakeFakeUartFd(CH_ACL_IN, mct_fds, fake_uart_);
77     MakeFakeUartFd(CH_ACL_OUT, mct_fds, fake_uart_);
78 
79     MctProtocol* mct_hci = new MctProtocol(mct_fds, event_cb_.AsStdFunction(),
80                                            acl_cb_.AsStdFunction());
81     fd_watcher_.WatchFdForNonBlockingReads(
82         mct_fds[CH_EVT], [mct_hci](int fd) { mct_hci->OnEventDataReady(fd); });
83     fd_watcher_.WatchFdForNonBlockingReads(
84         mct_fds[CH_ACL_IN], [mct_hci](int fd) { mct_hci->OnAclDataReady(fd); });
85     protocol_ = mct_hci;
86   }
87 
MakeFakeUartFd(int index,int * host_side,int * controller_side)88   void MakeFakeUartFd(int index, int* host_side, int* controller_side) {
89     int sockfd[2];
90     socketpair(AF_LOCAL, SOCK_STREAM, 0, sockfd);
91     host_side[index] = sockfd[0];
92     controller_side[index] = sockfd[1];
93   }
94 
TearDown()95   void TearDown() override { fd_watcher_.StopWatchingFileDescriptors(); }
96 
SendAndReadUartOutbound(uint8_t type,char * data,int outbound_fd)97   void SendAndReadUartOutbound(uint8_t type, char* data, int outbound_fd) {
98     ALOGD("%s sending", __func__);
99     int data_length = strlen(data);
100     protocol_->Send(type, (uint8_t*)data, data_length);
101 
102     ALOGD("%s reading", __func__);
103     int i;
104     for (i = 0; i < data_length; i++) {
105       fd_set read_fds;
106       FD_ZERO(&read_fds);
107       FD_SET(outbound_fd, &read_fds);
108       TEMP_FAILURE_RETRY(select(outbound_fd + 1, &read_fds, NULL, NULL, NULL));
109 
110       char byte;
111       TEMP_FAILURE_RETRY(read(outbound_fd, &byte, 1));
112 
113       EXPECT_EQ(data[i], byte);
114     }
115 
116     EXPECT_EQ(i, data_length);
117   }
118 
WriteAndExpectInboundAclData(char * payload)119   void WriteAndExpectInboundAclData(char* payload) {
120     // handle[2] + size[2]
121     char preamble[4] = {19, 92, 0, 0};
122     int length = strlen(payload);
123     preamble[2] = length & 0xFF;
124     preamble[3] = (length >> 8) & 0xFF;
125 
126     ALOGD("%s writing", __func__);
127     TEMP_FAILURE_RETRY(
128         write(fake_uart_[CH_ACL_IN], preamble, sizeof(preamble)));
129     TEMP_FAILURE_RETRY(write(fake_uart_[CH_ACL_IN], payload, strlen(payload)));
130 
131     ALOGD("%s waiting", __func__);
132     std::mutex mutex;
133     std::condition_variable done;
134     EXPECT_CALL(acl_cb_,
135                 Call(HidlVecMatches(preamble, sizeof(preamble), payload)))
136         .WillOnce(Notify(&mutex, &done));
137 
138     // Fail if it takes longer than 100 ms.
139     auto timeout_time =
140         std::chrono::steady_clock::now() + std::chrono::milliseconds(100);
141     {
142       std::unique_lock<std::mutex> lock(mutex);
143       done.wait_until(lock, timeout_time);
144     }
145   }
146 
WriteAndExpectInboundEvent(char * payload)147   void WriteAndExpectInboundEvent(char* payload) {
148     // event_code[1] + size[1]
149     char preamble[2] = {9, 0};
150     preamble[1] = strlen(payload) & 0xFF;
151 
152     ALOGD("%s writing", __func__);
153     TEMP_FAILURE_RETRY(write(fake_uart_[CH_EVT], preamble, sizeof(preamble)));
154     TEMP_FAILURE_RETRY(write(fake_uart_[CH_EVT], payload, strlen(payload)));
155 
156     ALOGD("%s waiting", __func__);
157     std::mutex mutex;
158     std::condition_variable done;
159     EXPECT_CALL(event_cb_,
160                 Call(HidlVecMatches(preamble, sizeof(preamble), payload)))
161         .WillOnce(Notify(&mutex, &done));
162 
163     // Fail if it takes longer than 100 ms.
164     auto timeout_time =
165         std::chrono::steady_clock::now() + std::chrono::milliseconds(100);
166     {
167       std::unique_lock<std::mutex> lock(mutex);
168       done.wait_until(lock, timeout_time);
169     }
170   }
171 
172   testing::MockFunction<void(const hidl_vec<uint8_t>&)> event_cb_;
173   testing::MockFunction<void(const hidl_vec<uint8_t>&)> acl_cb_;
174   async::AsyncFdWatcher fd_watcher_;
175   MctProtocol* protocol_;
176   int fake_uart_[CH_MAX];
177 };
178 
179 // Test sending data sends correct data onto the UART
TEST_F(MctProtocolTest,TestSends)180 TEST_F(MctProtocolTest, TestSends) {
181   SendAndReadUartOutbound(HCI_PACKET_TYPE_COMMAND, sample_data1,
182                           fake_uart_[CH_CMD]);
183   SendAndReadUartOutbound(HCI_PACKET_TYPE_ACL_DATA, sample_data2,
184                           fake_uart_[CH_ACL_OUT]);
185 }
186 
187 // Ensure we properly parse data coming from the UART
TEST_F(MctProtocolTest,TestReads)188 TEST_F(MctProtocolTest, TestReads) {
189   WriteAndExpectInboundAclData(acl_data);
190   WriteAndExpectInboundEvent(event_data);
191 }
192 
193 }  // namespace implementation
194 }  // namespace V1_0
195 }  // namespace bluetooth
196 }  // namespace hardware
197 }  // namespace android
198