Home | History | Annotate | Download | only in test
      1 /******************************************************************************
      2  *
      3  *  Copyright (C) 2014 Google, Inc.
      4  *
      5  *  Licensed under the Apache License, Version 2.0 (the "License");
      6  *  you may not use this file except in compliance with the License.
      7  *  You may obtain a copy of the License at:
      8  *
      9  *  http://www.apache.org/licenses/LICENSE-2.0
     10  *
     11  *  Unless required by applicable law or agreed to in writing, software
     12  *  distributed under the License is distributed on an "AS IS" BASIS,
     13  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     14  *  See the License for the specific language governing permissions and
     15  *  limitations under the License.
     16  *
     17  ******************************************************************************/
     18 
     19 #include <gtest/gtest.h>
     20 
     21 #include "AllocationTestHarness.h"
     22 
     23 extern "C" {
     24 #include <stdint.h>
     25 #include <sys/types.h>
     26 #include <sys/socket.h>
     27 #include <unistd.h>
     28 
     29 #include "osi/include/osi.h"
     30 #include "osi/include/semaphore.h"
     31 #include "hci_hal.h"
     32 #include "test_stubs.h"
     33 #include "vendor.h"
     34 }
     35 
     36 DECLARE_TEST_MODES(
     37   init,
     38   open,
     39   close_fn,
     40   transmit,
     41   read_synchronous,
     42   read_async_reentry
     43 );
     44 
     45 static char sample_data1[100] = "A point is that which has no part.";
     46 static char sample_data2[100] = "A line is breadthless length.";
     47 static char sample_data3[100] = "The ends of a line are points.";
     48 static char acl_data[100] =     "A straight line is a line which lies evenly with the points on itself.";
     49 static char event_data[100] =   "The edges of a surface are lines.";
     50 
     51 static const hci_hal_t *hal;
     52 static int command_out_fd;
     53 static int acl_out_fd;
     54 static int acl_in_fd;
     55 static int event_in_fd;
     56 static int reentry_i = 0;
     57 
     58 static semaphore_t *done;
     59 static semaphore_t *reentry_semaphore;
     60 
     61 static void expect_packet_synchronous(serial_data_type_t type, char *packet_data) {
     62   int length = strlen(packet_data);
     63   for (int i = 0; i < length; i++) {
     64     uint8_t byte;
     65     EXPECT_EQ((size_t)1, hal->read_data(type, &byte, 1));
     66     EXPECT_EQ(packet_data[i], byte);
     67   }
     68 
     69   hal->packet_finished(type);
     70 }
     71 
     72 STUB_FUNCTION(int, vendor_send_command, (vendor_opcode_t opcode, void *param))
     73   DURING(open) AT_CALL(0) {
     74     EXPECT_EQ(VENDOR_OPEN_USERIAL, opcode);
     75     ((int *)param)[CH_CMD] = command_out_fd;
     76     ((int *)param)[CH_ACL_OUT] = acl_out_fd;
     77     ((int *)param)[CH_ACL_IN] = acl_in_fd;
     78     ((int *)param)[CH_EVT] = event_in_fd;
     79     return 4;
     80   }
     81 
     82   DURING(close_fn) AT_CALL(0) {
     83     EXPECT_EQ(VENDOR_CLOSE_USERIAL, opcode);
     84     return 0;
     85   }
     86 
     87   UNEXPECTED_CALL;
     88   return 0;
     89 }
     90 
     91 STUB_FUNCTION(void, data_ready_callback, (serial_data_type_t type))
     92   DURING(read_synchronous) {
     93     AT_CALL(0) {
     94       EXPECT_EQ(DATA_TYPE_ACL, type);
     95       expect_packet_synchronous(type, acl_data);
     96       semaphore_post(done);
     97       return;
     98     }
     99     AT_CALL(1) {
    100       EXPECT_EQ(DATA_TYPE_EVENT, type);
    101       expect_packet_synchronous(type, event_data);
    102       semaphore_post(done);
    103       return;
    104     }
    105   }
    106 
    107   DURING(read_async_reentry) {
    108     EXPECT_EQ(DATA_TYPE_ACL, type);
    109 
    110     uint8_t byte;
    111     size_t bytes_read;
    112     while ((bytes_read = hal->read_data(type, &byte, 1)) != 0) {
    113       EXPECT_EQ(sample_data3[reentry_i], byte);
    114       semaphore_post(reentry_semaphore);
    115       reentry_i++;
    116       if (reentry_i == (int)strlen(sample_data3)) {
    117         hal->packet_finished(type);
    118         return;
    119       }
    120     }
    121 
    122     return;
    123   }
    124 
    125   UNEXPECTED_CALL;
    126 }
    127 
    128 static void reset_for(TEST_MODES_T next) {
    129   RESET_CALL_COUNT(vendor_send_command);
    130   RESET_CALL_COUNT(data_ready_callback);
    131   CURRENT_TEST_MODE = next;
    132 }
    133 
    134 class HciHalMctTest : public AllocationTestHarness {
    135   protected:
    136     virtual void SetUp() {
    137       AllocationTestHarness::SetUp();
    138       hal = hci_hal_mct_get_test_interface(&vendor);
    139       vendor.send_command = vendor_send_command;
    140       callbacks.data_ready = data_ready_callback;
    141 
    142       socketpair(AF_LOCAL, SOCK_STREAM, 0, command_sockfd);
    143       socketpair(AF_LOCAL, SOCK_STREAM, 0, event_sockfd);
    144       socketpair(AF_LOCAL, SOCK_STREAM, 0, acl_in_sockfd);
    145       socketpair(AF_LOCAL, SOCK_STREAM, 0, acl_out_sockfd);
    146       command_out_fd = command_sockfd[0];
    147       acl_out_fd = acl_out_sockfd[0];
    148       acl_in_fd = acl_in_sockfd[0];
    149       event_in_fd = event_sockfd[0];
    150 
    151       done = semaphore_new(0);
    152       thread = thread_new("hal_test");
    153 
    154       reset_for(init);
    155       EXPECT_TRUE(hal->init(&callbacks, thread));
    156 
    157       reset_for(open);
    158       EXPECT_TRUE(hal->open());
    159       EXPECT_CALL_COUNT(vendor_send_command, 1);
    160     }
    161 
    162     virtual void TearDown() {
    163       reset_for(close_fn);
    164       hal->close();
    165       EXPECT_CALL_COUNT(vendor_send_command, 1);
    166 
    167       semaphore_free(done);
    168       thread_free(thread);
    169       AllocationTestHarness::TearDown();
    170     }
    171 
    172     int command_sockfd[2];
    173     int event_sockfd[2];
    174     int acl_in_sockfd[2];
    175     int acl_out_sockfd[2];
    176     vendor_t vendor;
    177     thread_t *thread;
    178     hci_hal_callbacks_t callbacks;
    179 };
    180 
    181 static void expect_socket_data(int fd, char *data) {
    182   int length = strlen(data);
    183   int i;
    184 
    185   for (i = 0; i < length; i++) {
    186     fd_set read_fds;
    187     FD_ZERO(&read_fds);
    188     FD_SET(fd, &read_fds);
    189     select(fd + 1, &read_fds, NULL, NULL, NULL);
    190 
    191     char byte;
    192     read(fd, &byte, 1);
    193 
    194     EXPECT_EQ(data[i], byte);
    195   }
    196 }
    197 
    198 static void write_packet(int fd, char *data) {
    199   write(fd, data, strlen(data));
    200 }
    201 
    202 static void write_packet_reentry(int fd, char *data) {
    203   int length = strlen(data);
    204   for (int i = 0; i < length; i++) {
    205     write(fd, &data[i], 1);
    206     semaphore_wait(reentry_semaphore);
    207   }
    208 }
    209 
    210 TEST_F(HciHalMctTest, test_transmit) {
    211   reset_for(transmit);
    212 
    213   // Send a command packet
    214   hal->transmit_data(DATA_TYPE_COMMAND, (uint8_t *)(sample_data1), strlen(sample_data1));
    215   expect_socket_data(command_sockfd[1], sample_data1);
    216 
    217   // Send an acl packet
    218   hal->transmit_data(DATA_TYPE_ACL, (uint8_t *)(sample_data2), strlen(sample_data2));
    219   expect_socket_data(acl_out_sockfd[1], sample_data2);
    220 }
    221 
    222 TEST_F(HciHalMctTest, test_read_synchronous) {
    223   reset_for(read_synchronous);
    224 
    225   write_packet(acl_in_sockfd[1], acl_data);
    226   semaphore_wait(done);
    227 
    228   write_packet(event_sockfd[1], event_data);
    229   semaphore_wait(done);
    230 
    231   EXPECT_CALL_COUNT(data_ready_callback, 2);
    232 }
    233 
    234 TEST_F(HciHalMctTest, test_read_async_reentry) {
    235   reset_for(read_async_reentry);
    236 
    237   reentry_semaphore = semaphore_new(0);
    238   reentry_i = 0;
    239 
    240   write_packet_reentry(acl_in_sockfd[1], sample_data3);
    241 
    242   // write_packet_reentry ensures the data has been received
    243   semaphore_free(reentry_semaphore);
    244 }
    245