Home | History | Annotate | Download | only in test
      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 
     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:
     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 
     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 
     95   void TearDown() override { fd_watcher_.StopWatchingFileDescriptors(); }
     96 
     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 
    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 
    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
    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
    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