blob: 911aabcfdea8b24da7057429a9e1136fd927f4b4 [file] [log] [blame]
Zach Johnsonb7ddf132014-08-20 23:12:33 -07001/******************************************************************************
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
Zach Johnson1e0ede72014-08-27 16:30:29 -070021#include "AllocationTestHarness.h"
22
Zach Johnsonb7ddf132014-08-20 23:12:33 -070023extern "C" {
24#include <stdint.h>
25#include <sys/types.h>
26#include <sys/socket.h>
27#include <unistd.h>
Zach Johnsonb7ddf132014-08-20 23:12:33 -070028
29#include "hci_hal.h"
30#include "osi.h"
31#include "semaphore.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);
44
45static char sample_data1[100] = "A point is that which has no part.";
46static char sample_data2[100] = "A line is breadthless length.";
47static char sample_data3[100] = "The ends of a line are points.";
48static char acl_data[100] = "A straight line is a line which lies evenly with the points on itself.";
49static char event_data[100] = "The edges of a surface are lines.";
50
Zach Johnsonbf8193b2014-09-08 09:56:35 -070051static const hci_hal_t *hal;
Zach Johnsonb7ddf132014-08-20 23:12:33 -070052static int command_out_fd;
53static int acl_out_fd;
54static int acl_in_fd;
55static int event_in_fd;
56static int reentry_i = 0;
57
58static semaphore_t *done;
59static semaphore_t *reentry_semaphore;
60
61static 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++) {
Zach Johnsonbb170c12014-08-21 21:00:43 -070064 uint8_t byte;
65 EXPECT_EQ((size_t)1, hal->read_data(type, &byte, 1, true));
66 EXPECT_EQ(packet_data[i], byte);
Zach Johnsonb7ddf132014-08-20 23:12:33 -070067 }
68
69 hal->packet_finished(type);
70}
71
72STUB_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
91STUB_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
Zach Johnsonbb170c12014-08-21 21:00:43 -0700110 uint8_t byte;
111 size_t bytes_read;
112 while ((bytes_read = hal->read_data(type, &byte, 1, false)) != 0) {
113 EXPECT_EQ(sample_data3[reentry_i], byte);
Zach Johnsonb7ddf132014-08-20 23:12:33 -0700114 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
128static 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
Zach Johnson1e0ede72014-08-27 16:30:29 -0700134class HciHalMctTest : public AllocationTestHarness {
Zach Johnsonb7ddf132014-08-20 23:12:33 -0700135 protected:
136 virtual void SetUp() {
Zach Johnson1e0ede72014-08-27 16:30:29 -0700137 AllocationTestHarness::SetUp();
Zach Johnsonb7ddf132014-08-20 23:12:33 -0700138 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);
Zach Johnson1e0ede72014-08-27 16:30:29 -0700169 AllocationTestHarness::TearDown();
Zach Johnsonb7ddf132014-08-20 23:12:33 -0700170 }
171
172 int command_sockfd[2];
173 int event_sockfd[2];
174 int acl_in_sockfd[2];
175 int acl_out_sockfd[2];
Zach Johnsonbf8193b2014-09-08 09:56:35 -0700176 vendor_t vendor;
Zach Johnsonb7ddf132014-08-20 23:12:33 -0700177 thread_t *thread;
178 hci_hal_callbacks_t callbacks;
179};
180
181static 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
198static void write_packet(int fd, char *data) {
199 write(fd, data, strlen(data));
200}
201
202static 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
210TEST_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
222TEST_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
234TEST_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}