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 "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 
     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:
     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 
     88   void TearDown() override { fd_watcher_.StopWatchingFileDescriptors(); }
     89 
     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 
    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 
    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 
    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
    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
    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