3 * BlueZ - Bluetooth protocol stack for Linux
5 * Copyright (C) 2013-2014 Intel Corporation. All rights reserved.
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
36 #include <sys/socket.h>
40 #include "src/shared/util.h"
42 #include "android/ipc-common.h"
43 #include "android/ipc.h"
45 static const char HAL_SK_PATH[] = "\0test_hal_socket";
47 #define SERVICE_ID_MAX 10
54 const struct ipc_handler *handlers;
55 uint8_t handlers_size;
70 const struct test_data *data;
74 static struct ipc *ipc = NULL;
76 static void context_quit(struct context *context)
78 g_main_loop_quit(context->main_loop);
81 static gboolean cmd_watch(GIOChannel *io, GIOCondition cond,
84 struct context *context = user_data;
85 const struct test_data *test_data = context->data;
86 const struct ipc_hdr *sent_msg = test_data->cmd;
90 struct ipc_hdr success_resp = {
91 .service_id = sent_msg->service_id,
92 .opcode = sent_msg->opcode,
96 if (cond & (G_IO_HUP | G_IO_ERR | G_IO_NVAL)) {
97 g_assert(test_data->disconnect);
101 g_assert(!test_data->disconnect);
103 sk = g_io_channel_unix_get_fd(io);
105 g_assert(read(sk, buf, sizeof(buf)) == sizeof(struct ipc_hdr));
106 g_assert(!memcmp(&success_resp, buf, sizeof(struct ipc_hdr)));
108 context_quit(context);
113 static gboolean notif_watch(GIOChannel *io, GIOCondition cond,
116 struct context *context = user_data;
117 const struct test_data *test_data = context->data;
119 if (cond & (G_IO_HUP | G_IO_ERR | G_IO_NVAL)) {
120 g_assert(test_data->disconnect);
124 g_assert(!test_data->disconnect);
129 static gboolean connect_handler(GIOChannel *io, GIOCondition cond,
132 struct context *context = user_data;
133 const struct test_data *test_data = context->data;
135 GIOCondition watch_cond;
138 if (cond & (G_IO_HUP | G_IO_ERR | G_IO_NVAL)) {
143 g_assert(!context->cmd_source || !context->notif_source);
145 sk = accept(context->sk, NULL, NULL);
148 new_io = g_io_channel_unix_new(sk);
150 watch_cond = G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL;
152 if (context->cmd_source && !context->notif_source) {
153 context->notif_source = g_io_add_watch(new_io, watch_cond,
154 notif_watch, context);
155 g_assert(context->notif_source > 0);
156 context->notif_io = new_io;
159 if (!context->cmd_source) {
160 context->cmd_source = g_io_add_watch(new_io, watch_cond,
162 context->cmd_io = new_io;
165 if (context->cmd_source && context->notif_source && !test_data->cmd)
166 context_quit(context);
171 static struct context *create_context(gconstpointer data)
173 struct context *context = g_new0(struct context, 1);
174 struct sockaddr_un addr;
178 context->main_loop = g_main_loop_new(NULL, FALSE);
179 g_assert(context->main_loop);
181 sk = socket(AF_LOCAL, SOCK_SEQPACKET, 0);
184 memset(&addr, 0, sizeof(addr));
185 addr.sun_family = AF_UNIX;
187 memcpy(addr.sun_path, HAL_SK_PATH, sizeof(HAL_SK_PATH));
189 ret = bind(sk, (struct sockaddr *) &addr, sizeof(addr));
195 io = g_io_channel_unix_new(sk);
197 g_io_channel_set_close_on_unref(io, TRUE);
199 context->source = g_io_add_watch(io,
200 G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL,
201 connect_handler, context);
202 g_assert(context->source > 0);
204 g_io_channel_unref(io);
207 context->data = data;
212 static void execute_context(struct context *context)
214 g_main_loop_run(context->main_loop);
216 g_io_channel_shutdown(context->notif_io, TRUE, NULL);
217 g_io_channel_shutdown(context->cmd_io, TRUE, NULL);
218 g_io_channel_unref(context->cmd_io);
219 g_io_channel_unref(context->notif_io);
221 g_source_remove(context->notif_source);
222 g_source_remove(context->cmd_source);
223 g_source_remove(context->source);
225 g_main_loop_unref(context->main_loop);
230 static void disconnected(void *data)
232 struct context *context = data;
234 g_assert(context->data->disconnect);
236 context_quit(context);
239 static void test_init(gconstpointer data)
241 struct context *context = create_context(data);
243 ipc = ipc_init(HAL_SK_PATH, sizeof(HAL_SK_PATH), SERVICE_ID_MAX,
248 execute_context(context);
254 static gboolean send_cmd(gpointer user_data)
256 struct context *context = user_data;
257 const struct test_data *test_data = context->data;
260 sk = g_io_channel_unix_get_fd(context->cmd_io);
263 g_assert(write(sk, test_data->cmd, test_data->cmd_size) ==
264 test_data->cmd_size);
269 static gboolean register_service(gpointer user_data)
271 struct context *context = user_data;
272 const struct test_data *test_data = context->data;
274 ipc_register(ipc, test_data->service, test_data->handlers,
275 test_data->handlers_size);
280 static gboolean unregister_service(gpointer user_data)
282 struct context *context = user_data;
283 const struct test_data *test_data = context->data;
285 ipc_unregister(ipc, test_data->service);
290 static void test_cmd(gconstpointer data)
292 struct context *context = create_context(data);
294 ipc = ipc_init(HAL_SK_PATH, sizeof(HAL_SK_PATH), SERVICE_ID_MAX,
295 true, disconnected, context);
299 g_idle_add(send_cmd, context);
301 execute_context(context);
307 static void test_cmd_reg(gconstpointer data)
309 struct context *context = create_context(data);
310 const struct test_data *test_data = context->data;
312 ipc = ipc_init(HAL_SK_PATH, sizeof(HAL_SK_PATH), SERVICE_ID_MAX,
313 true, disconnected, context);
317 g_idle_add(register_service, context);
318 g_idle_add(send_cmd, context);
320 execute_context(context);
322 ipc_unregister(ipc, test_data->service);
328 static void test_cmd_reg_1(gconstpointer data)
330 struct context *context = create_context(data);
332 ipc = ipc_init(HAL_SK_PATH, sizeof(HAL_SK_PATH), SERVICE_ID_MAX,
333 true, disconnected, context);
337 g_idle_add(register_service, context);
338 g_idle_add(unregister_service, context);
339 g_idle_add(send_cmd, context);
341 execute_context(context);
347 static void test_cmd_handler_1(const void *buf, uint16_t len)
349 ipc_send_rsp(ipc, 0, 1, 0);
352 static void test_cmd_handler_2(const void *buf, uint16_t len)
354 ipc_send_rsp(ipc, 0, 2, 0);
357 static void test_cmd_handler_invalid(const void *buf, uint16_t len)
362 static const struct test_data test_init_1 = {};
364 static const struct ipc_hdr test_cmd_1_hdr = {
370 static const struct ipc_hdr test_cmd_2_hdr = {
376 static const struct test_data test_cmd_service_invalid_1 = {
377 .cmd = &test_cmd_1_hdr,
378 .cmd_size = sizeof(test_cmd_1_hdr),
382 static const struct ipc_handler cmd_handlers[] = {
383 { test_cmd_handler_1, false, 0 }
386 static const struct test_data test_cmd_service_valid_1 = {
387 .cmd = &test_cmd_1_hdr,
388 .cmd_size = sizeof(test_cmd_1_hdr),
390 .handlers = cmd_handlers,
394 static const struct test_data test_cmd_service_invalid_2 = {
395 .cmd = &test_cmd_1_hdr,
396 .cmd_size = sizeof(test_cmd_1_hdr),
398 .handlers = cmd_handlers,
403 static const struct ipc_handler cmd_handlers_invalid_2[] = {
404 { test_cmd_handler_1, false, 0 },
405 { test_cmd_handler_invalid, false, 0 }
408 static const struct ipc_handler cmd_handlers_invalid_1[] = {
409 { test_cmd_handler_invalid, false, 0 },
410 { test_cmd_handler_2, false, 0 },
413 static const struct test_data test_cmd_opcode_valid_1 = {
414 .cmd = &test_cmd_1_hdr,
415 .cmd_size = sizeof(test_cmd_1_hdr),
417 .handlers = cmd_handlers_invalid_2,
421 static const struct test_data test_cmd_opcode_valid_2 = {
422 .cmd = &test_cmd_2_hdr,
423 .cmd_size = sizeof(test_cmd_2_hdr),
425 .handlers = cmd_handlers_invalid_1,
429 static const struct test_data test_cmd_opcode_invalid_1 = {
430 .cmd = &test_cmd_2_hdr,
431 .cmd_size = sizeof(test_cmd_2_hdr),
433 .handlers = cmd_handlers,
438 static const struct test_data test_cmd_hdr_invalid = {
439 .cmd = &test_cmd_1_hdr,
440 .cmd_size = sizeof(test_cmd_1_hdr) - 1,
442 .handlers = cmd_handlers,
447 #define VARDATA_EX1 "some data example"
451 uint8_t data[IPC_MTU - sizeof(struct ipc_hdr)];
452 } __attribute__((packed));
454 static const struct vardata test_cmd_vardata = {
457 .hdr.len = sizeof(VARDATA_EX1),
461 static const struct ipc_handler cmd_vardata_handlers[] = {
462 { test_cmd_handler_1, true, sizeof(VARDATA_EX1) }
465 static const struct test_data test_cmd_vardata_valid = {
466 .cmd = &test_cmd_vardata,
467 .cmd_size = sizeof(struct ipc_hdr) + sizeof(VARDATA_EX1),
469 .handlers = cmd_vardata_handlers,
473 static const struct ipc_handler cmd_vardata_handlers_valid2[] = {
474 { test_cmd_handler_1, true, sizeof(VARDATA_EX1) - 1 }
477 static const struct test_data test_cmd_vardata_valid_2 = {
478 .cmd = &test_cmd_vardata,
479 .cmd_size = sizeof(struct ipc_hdr) + sizeof(VARDATA_EX1),
481 .handlers = cmd_vardata_handlers_valid2,
485 static const struct test_data test_cmd_vardata_invalid_1 = {
486 .cmd = &test_cmd_vardata,
487 .cmd_size = sizeof(struct ipc_hdr) + sizeof(VARDATA_EX1) - 1,
489 .handlers = cmd_vardata_handlers,
494 static const struct ipc_hdr test_cmd_service_offrange_hdr = {
495 .service_id = SERVICE_ID_MAX + 1,
500 static const struct test_data test_cmd_service_offrange = {
501 .cmd = &test_cmd_service_offrange_hdr,
502 .cmd_size = sizeof(struct ipc_hdr),
504 .handlers = cmd_handlers,
509 static const struct vardata test_cmd_invalid_data_1 = {
512 .hdr.len = sizeof(VARDATA_EX1),
516 static const struct test_data test_cmd_msg_invalid_1 = {
517 .cmd = &test_cmd_invalid_data_1,
518 .cmd_size = sizeof(struct ipc_hdr) + sizeof(VARDATA_EX1) - 1,
520 .handlers = cmd_handlers,
525 static const struct vardata test_cmd_invalid_data_2 = {
528 .hdr.len = sizeof(VARDATA_EX1) - 1,
532 static const struct test_data test_cmd_msg_invalid_2 = {
533 .cmd = &test_cmd_invalid_data_2,
534 .cmd_size = sizeof(struct ipc_hdr) + sizeof(VARDATA_EX1),
536 .handlers = cmd_handlers,
541 int main(int argc, char *argv[])
543 g_test_init(&argc, &argv, NULL);
545 if (g_test_verbose())
546 __btd_log_init("*", 0);
548 g_test_add_data_func("/android_ipc/init", &test_init_1, test_init);
549 g_test_add_data_func("/android_ipc/service_invalid_1",
550 &test_cmd_service_invalid_1, test_cmd);
551 g_test_add_data_func("/android_ipc/service_valid_1",
552 &test_cmd_service_valid_1, test_cmd_reg);
553 g_test_add_data_func("/android_ipc/service_invalid_2",
554 &test_cmd_service_invalid_2, test_cmd_reg_1);
555 g_test_add_data_func("/android_ipc/opcode_valid_1",
556 &test_cmd_opcode_valid_1, test_cmd_reg);
557 g_test_add_data_func("/android_ipc/opcode_valid_2",
558 &test_cmd_opcode_valid_2, test_cmd_reg);
559 g_test_add_data_func("/android_ipc/opcode_invalid_1",
560 &test_cmd_opcode_invalid_1, test_cmd_reg);
561 g_test_add_data_func("/android_ipc/vardata_valid",
562 &test_cmd_vardata_valid, test_cmd_reg);
563 g_test_add_data_func("/android_ipc/vardata_valid_2",
564 &test_cmd_vardata_valid_2, test_cmd_reg);
565 g_test_add_data_func("/android_ipc/vardata_invalid_1",
566 &test_cmd_vardata_invalid_1, test_cmd_reg);
567 g_test_add_data_func("/android_ipc/service_offrange",
568 &test_cmd_service_offrange, test_cmd_reg);
569 g_test_add_data_func("/android_ipc/hdr_invalid",
570 &test_cmd_hdr_invalid, test_cmd_reg);
571 g_test_add_data_func("/android_ipc/msg_invalid_1",
572 &test_cmd_msg_invalid_1, test_cmd_reg);
573 g_test_add_data_func("/android_ipc/msg_invalid_2",
574 &test_cmd_msg_invalid_2, test_cmd_reg);