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 
expect_packet_synchronous(serial_data_type_t type,char * packet_data)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))
DURING(open)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