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 
expect_packet_synchronous(serial_data_type_t type,char * packet_data)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))
DURING(open)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, char *data) {
196   write(fd, &first_byte, 1);
197   write(fd, data, strlen(data));
198 }
199 
200 static 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 
210 TEST_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 
226 TEST_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 
239 TEST_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 
251 TEST_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