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   type_byte_only
     44 );
     45 
     46 // Use as packet type to test stream_corrupted_during_le_scan_workaround()
     47 static const uint8_t HCI_BLE_EVENT = 0x3e;
     48 
     49 static char sample_data1[100] = "A point is that which has no part.";
     50 static char sample_data2[100] = "A line is breadthless length.";
     51 static char sample_data3[100] = "The ends of a line are points.";
     52 static char acl_data[100] =     "A straight line is a line which lies evenly with the points on itself.";
     53 static char sco_data[100] =     "A surface is that which has length and breadth only.";
     54 static char event_data[100] =   "The edges of a surface are lines.";
     55 
     56 // Test data for stream_corrupted_during_le_scan_workaround()
     57 static char corrupted_data[] = { 0x5 /* length of remaining data */, 'H', 'e', 'l', 'l', 'o' };
     58 
     59 static const hci_hal_t *hal;
     60 static int dummy_serial_fd;
     61 static int reentry_i = 0;
     62 
     63 static semaphore_t *done;
     64 static semaphore_t *reentry_semaphore;
     65 
     66 static void expect_packet_synchronous(serial_data_type_t type, char *packet_data) {
     67   int length = strlen(packet_data);
     68   for (int i = 0; i < length; i++) {
     69     uint8_t byte;
     70     EXPECT_EQ((size_t)1, hal->read_data(type, &byte, 1));
     71     EXPECT_EQ(packet_data[i], byte);
     72   }
     73 
     74   hal->packet_finished(type);
     75 }
     76 
     77 STUB_FUNCTION(int, vendor_send_command, (vendor_opcode_t opcode, void *param))
     78   DURING(open) AT_CALL(0) {
     79     EXPECT_EQ(VENDOR_OPEN_USERIAL, opcode);
     80     // Give back the dummy fd and the number 1 to say we opened 1 port
     81     ((int *)param)[0] = dummy_serial_fd;
     82     return 1;
     83   }
     84 
     85   DURING(close_fn) AT_CALL(0) {
     86     EXPECT_EQ(VENDOR_CLOSE_USERIAL, opcode);
     87     return 0;
     88   }
     89 
     90   UNEXPECTED_CALL;
     91   return 0;
     92 }
     93 
     94 STUB_FUNCTION(void, data_ready_callback, (serial_data_type_t type))
     95   DURING(read_synchronous) {
     96     AT_CALL(0) {
     97       EXPECT_EQ(DATA_TYPE_ACL, type);
     98       expect_packet_synchronous(type, acl_data);
     99       return;
    100     }
    101     AT_CALL(1) {
    102       EXPECT_EQ(DATA_TYPE_SCO, type);
    103       expect_packet_synchronous(type, sco_data);
    104       return;
    105     }
    106     AT_CALL(2) {
    107       EXPECT_EQ(DATA_TYPE_EVENT, type);
    108       expect_packet_synchronous(type, event_data);
    109       semaphore_post(done);
    110       return;
    111     }
    112   }
    113 
    114   DURING(read_async_reentry) {
    115     EXPECT_EQ(DATA_TYPE_ACL, type);
    116 
    117     uint8_t byte;
    118     size_t bytes_read;
    119     while ((bytes_read = hal->read_data(type, &byte, 1)) != 0) {
    120       EXPECT_EQ(sample_data3[reentry_i], byte);
    121       semaphore_post(reentry_semaphore);
    122       reentry_i++;
    123       if (reentry_i == (int)strlen(sample_data3)) {
    124         hal->packet_finished(type);
    125         return;
    126       }
    127     }
    128 
    129     return;
    130   }
    131 
    132   UNEXPECTED_CALL;
    133 }
    134 
    135 static void reset_for(TEST_MODES_T next) {
    136   RESET_CALL_COUNT(vendor_send_command);
    137   RESET_CALL_COUNT(data_ready_callback);
    138   CURRENT_TEST_MODE = next;
    139 }
    140 
    141 class HciHalH4Test : public AllocationTestHarness {
    142   protected:
    143     virtual void SetUp() {
    144       AllocationTestHarness::SetUp();
    145       hal = hci_hal_h4_get_test_interface(&vendor);
    146       vendor.send_command = vendor_send_command;
    147       callbacks.data_ready = data_ready_callback;
    148 
    149       socketpair(AF_LOCAL, SOCK_STREAM, 0, sockfd);
    150       dummy_serial_fd = sockfd[0];
    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 sockfd[2];
    173     vendor_t vendor;
    174     thread_t *thread;
    175     hci_hal_callbacks_t callbacks;
    176 };
    177 
    178 static void expect_socket_data(int fd, char first_byte, char *data) {
    179   int length = strlen(data) + 1; // + 1 for data type code
    180   int i;
    181 
    182   for (i = 0; i < length; i++) {
    183     fd_set read_fds;
    184     FD_ZERO(&read_fds);
    185     FD_SET(fd, &read_fds);
    186     select(fd + 1, &read_fds, NULL, NULL, NULL);
    187 
    188     char byte;
    189     read(fd, &byte, 1);
    190 
    191     EXPECT_EQ(i == 0 ? first_byte : data[i - 1], byte);
    192   }
    193 }
    194 
    195 static void write_packet(int fd, char first_byte, const void *data,
    196                          size_t datalen) {
    197   write(fd, &first_byte, 1);
    198   write(fd, data, datalen);
    199 }
    200 
    201 static void write_packet_reentry(int fd, char first_byte, const void *data,
    202                                  size_t datalen) {
    203   write(fd, &first_byte, 1);
    204 
    205   for (size_t i = 0; i < datalen; i++) {
    206     write(fd, static_cast<const uint8_t *>(data) + i, 1);
    207     semaphore_wait(reentry_semaphore);
    208   }
    209 }
    210 
    211 TEST_F(HciHalH4Test, test_transmit) {
    212   reset_for(transmit);
    213 
    214   // Send a command packet
    215   hal->transmit_data(DATA_TYPE_COMMAND, (uint8_t *)(sample_data1 + 1), strlen(sample_data1 + 1));
    216   expect_socket_data(sockfd[1], DATA_TYPE_COMMAND, sample_data1 + 1);
    217 
    218   // Send an acl packet
    219   hal->transmit_data(DATA_TYPE_ACL, (uint8_t *)(sample_data2 + 1), strlen(sample_data2 + 1));
    220   expect_socket_data(sockfd[1], DATA_TYPE_ACL, sample_data2 + 1);
    221 
    222   // Send an sco packet
    223   hal->transmit_data(DATA_TYPE_SCO, (uint8_t *)(sample_data3 + 1), strlen(sample_data3 + 1));
    224   expect_socket_data(sockfd[1], DATA_TYPE_SCO, sample_data3 + 1);
    225 }
    226 
    227 TEST_F(HciHalH4Test, test_read_synchronous) {
    228   reset_for(read_synchronous);
    229 
    230   write_packet(sockfd[1], DATA_TYPE_ACL, acl_data, strlen(acl_data));
    231   write_packet(sockfd[1], HCI_BLE_EVENT, corrupted_data,
    232                sizeof(corrupted_data));
    233   write_packet(sockfd[1], DATA_TYPE_SCO, sco_data, strlen(sco_data));
    234   write_packet(sockfd[1], DATA_TYPE_EVENT, event_data, strlen(event_data));
    235 
    236   // Wait for all data to be received before calling the test good
    237   semaphore_wait(done);
    238   EXPECT_CALL_COUNT(data_ready_callback, 3);
    239 }
    240 
    241 TEST_F(HciHalH4Test, test_read_async_reentry) {
    242   reset_for(read_async_reentry);
    243 
    244   reentry_semaphore = semaphore_new(0);
    245   reentry_i = 0;
    246 
    247   write_packet_reentry(sockfd[1], DATA_TYPE_ACL, sample_data3,
    248                        strlen(sample_data3));
    249 
    250   // write_packet_reentry ensures the data has been received
    251   semaphore_free(reentry_semaphore);
    252 }
    253 
    254 TEST_F(HciHalH4Test, test_type_byte_only_must_not_signal_data_ready) {
    255   reset_for(type_byte_only);
    256 
    257   char byte = DATA_TYPE_ACL;
    258   write(sockfd[1], &byte, 1);
    259 
    260   fd_set read_fds;
    261 
    262   // Wait until the byte we wrote was picked up
    263   do {
    264     FD_ZERO(&read_fds);
    265     FD_SET(sockfd[0], &read_fds);
    266 
    267     struct timeval timeout;
    268     timeout.tv_sec = 0;
    269     timeout.tv_usec = 0;
    270 
    271     select(sockfd[0] + 1, &read_fds, NULL, NULL, &timeout);
    272   } while(FD_ISSET(sockfd[0], &read_fds));
    273 }
    274