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 23extern "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 36DECLARE_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() 47static const uint8_t HCI_BLE_EVENT = 0x3e; 48 49static char sample_data1[100] = "A point is that which has no part."; 50static char sample_data2[100] = "A line is breadthless length."; 51static char sample_data3[100] = "The ends of a line are points."; 52static char acl_data[100] = "A straight line is a line which lies evenly with the points on itself."; 53static char sco_data[100] = "A surface is that which has length and breadth only."; 54static char event_data[100] = "The edges of a surface are lines."; 55 56// Test data for stream_corrupted_during_le_scan_workaround() 57static char corrupted_data[] = { 0x5 /* length of remaining data */, 'H', 'e', 'l', 'l', 'o' }; 58 59static const hci_hal_t *hal; 60static int dummy_serial_fd; 61static int reentry_i = 0; 62 63static semaphore_t *done; 64static semaphore_t *reentry_semaphore; 65 66static 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 77STUB_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 94STUB_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 135static 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 141class 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 178static 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 195static void write_packet(int fd, char first_byte, char *data) { 196 write(fd, &first_byte, 1); 197 write(fd, data, strlen(data)); 198} 199 200static void write_packet_reentry(int fd, char first_byte, char *data) { 201 write(fd, &first_byte, 1); 202 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 210TEST_F(HciHalH4Test, test_transmit) { 211 reset_for(transmit); 212 213 // Send a command packet 214 hal->transmit_data(DATA_TYPE_COMMAND, (uint8_t *)(sample_data1 + 1), strlen(sample_data1 + 1)); 215 expect_socket_data(sockfd[1], DATA_TYPE_COMMAND, sample_data1 + 1); 216 217 // Send an acl packet 218 hal->transmit_data(DATA_TYPE_ACL, (uint8_t *)(sample_data2 + 1), strlen(sample_data2 + 1)); 219 expect_socket_data(sockfd[1], DATA_TYPE_ACL, sample_data2 + 1); 220 221 // Send an sco packet 222 hal->transmit_data(DATA_TYPE_SCO, (uint8_t *)(sample_data3 + 1), strlen(sample_data3 + 1)); 223 expect_socket_data(sockfd[1], DATA_TYPE_SCO, sample_data3 + 1); 224} 225 226TEST_F(HciHalH4Test, test_read_synchronous) { 227 reset_for(read_synchronous); 228 229 write_packet(sockfd[1], DATA_TYPE_ACL, acl_data); 230 write_packet(sockfd[1], HCI_BLE_EVENT, corrupted_data); 231 write_packet(sockfd[1], DATA_TYPE_SCO, sco_data); 232 write_packet(sockfd[1], DATA_TYPE_EVENT, event_data); 233 234 // Wait for all data to be received before calling the test good 235 semaphore_wait(done); 236 EXPECT_CALL_COUNT(data_ready_callback, 3); 237} 238 239TEST_F(HciHalH4Test, test_read_async_reentry) { 240 reset_for(read_async_reentry); 241 242 reentry_semaphore = semaphore_new(0); 243 reentry_i = 0; 244 245 write_packet_reentry(sockfd[1], DATA_TYPE_ACL, sample_data3); 246 247 // write_packet_reentry ensures the data has been received 248 semaphore_free(reentry_semaphore); 249} 250 251TEST_F(HciHalH4Test, test_type_byte_only_must_not_signal_data_ready) { 252 reset_for(type_byte_only); 253 254 char byte = DATA_TYPE_ACL; 255 write(sockfd[1], &byte, 1); 256 257 fd_set read_fds; 258 259 // Wait until the byte we wrote was picked up 260 do { 261 FD_ZERO(&read_fds); 262 FD_SET(sockfd[0], &read_fds); 263 264 struct timeval timeout; 265 timeout.tv_sec = 0; 266 timeout.tv_usec = 0; 267 268 select(sockfd[0] + 1, &read_fds, NULL, NULL, &timeout); 269 } while(FD_ISSET(sockfd[0], &read_fds)); 270} 271