* [PATCHv3 1/5] android/unit: Add android IPC unit tests
@ 2014-01-16 10:04 Marcin Kraglak
2014-01-16 10:04 ` [PATCHv3 2/5] android/ipc: Remove watches on cleanup Marcin Kraglak
` (4 more replies)
0 siblings, 5 replies; 6+ messages in thread
From: Marcin Kraglak @ 2014-01-16 10:04 UTC (permalink / raw)
To: linux-bluetooth
It will test ipc library. First test case will check
ipc_init() call.
---
.gitignore | 1 +
android/Makefile.am | 8 ++
android/test-ipc.c | 277 ++++++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 286 insertions(+)
create mode 100644 android/test-ipc.c
diff --git a/.gitignore b/.gitignore
index ac76fe2..ddd562a 100644
--- a/.gitignore
+++ b/.gitignore
@@ -114,3 +114,4 @@ android/bluetoothd
android/haltest
android/android-tester
android/bluetoothd-snoop
+android/test-ipc
diff --git a/android/Makefile.am b/android/Makefile.am
index cd4a526..0c61317 100644
--- a/android/Makefile.am
+++ b/android/Makefile.am
@@ -117,6 +117,14 @@ android_android_tester_LDADD = lib/libbluetooth-internal.la @GLIB_LIBS@
android_android_tester_LDFLAGS = -pthread -ldl
+noinst_PROGRAMS += android/test-ipc
+
+android_test_ipc_SOURCES = android/test-ipc.c \
+ src/shared/util.h src/shared/util.c \
+ src/log.h src/log.c \
+ android/ipc.c android/ipc.h
+android_test_ipc_LDADD = @GLIB_LIBS@
+
plugin_LTLIBRARIES += android/audio.a2dp.default.la
android_audio_a2dp_default_la_SOURCES = android/audio-msg.h \
diff --git a/android/test-ipc.c b/android/test-ipc.c
new file mode 100644
index 0000000..6ac1175
--- /dev/null
+++ b/android/test-ipc.c
@@ -0,0 +1,277 @@
+/*
+ *
+ * BlueZ - Bluetooth protocol stack for Linux
+ *
+ * Copyright (C) 2014 Intel Corporation. All rights reserved.
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include <stdio.h>
+#include <errno.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdbool.h>
+#include <inttypes.h>
+#include <string.h>
+#include <fcntl.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <sys/signalfd.h>
+
+#include <glib.h>
+#include "src/shared/util.h"
+#include "src/log.h"
+#include "android/hal-msg.h"
+#include "android/ipc.h"
+
+struct test_data {
+ uint32_t expected_signal;
+};
+
+struct context {
+ GMainLoop *main_loop;
+
+ int sk;
+
+ guint source;
+ guint cmd_source;
+ guint notif_source;
+
+ GIOChannel *cmd_io;
+ GIOChannel *notif_io;
+ GIOChannel *signal_io;
+
+ guint signal_source;
+
+ const struct test_data *data;
+};
+
+static void context_quit(struct context *context)
+{
+ g_main_loop_quit(context->main_loop);
+}
+
+static gboolean cmd_watch(GIOChannel *io, GIOCondition cond,
+ gpointer user_data)
+{
+ if (cond & (G_IO_HUP | G_IO_ERR | G_IO_NVAL)) {
+ g_assert(FALSE);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static gboolean notif_watch(GIOChannel *io, GIOCondition cond,
+ gpointer user_data)
+{
+ if (cond & (G_IO_HUP | G_IO_ERR | G_IO_NVAL)) {
+ g_assert(FALSE);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static gboolean connect_handler(GIOChannel *io, GIOCondition cond,
+ gpointer user_data)
+{
+ struct context *context = user_data;
+ GIOChannel *new_io;
+ GIOCondition watch_cond;
+ int sk;
+
+ if (cond & (G_IO_HUP | G_IO_ERR | G_IO_NVAL)) {
+ g_assert(FALSE);
+ return FALSE;
+ }
+
+ g_assert(!context->cmd_source || !context->notif_source);
+
+ sk = accept(context->sk, NULL, NULL);
+ g_assert(sk >= 0);
+
+ new_io = g_io_channel_unix_new(sk);
+
+ watch_cond = G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL;
+
+ if (context->cmd_source && !context->notif_source) {
+ context->notif_source = g_io_add_watch(new_io, watch_cond,
+ notif_watch, context);
+ g_assert(context->notif_source > 0);
+ context->notif_io = new_io;
+ }
+
+ if (!context->cmd_source) {
+ context->cmd_source = g_io_add_watch(new_io, watch_cond,
+ cmd_watch, context);
+ context->cmd_io = new_io;
+ }
+
+ if (context->cmd_source && context->notif_source)
+ context_quit(context);
+
+ return TRUE;
+}
+
+static gboolean signal_handler(GIOChannel *channel, GIOCondition cond,
+ gpointer user_data)
+{
+ struct context *context = user_data;
+ const struct test_data *test_data = context->data;
+ struct signalfd_siginfo si;
+ ssize_t result;
+ int fd;
+
+ if (cond & (G_IO_NVAL | G_IO_ERR | G_IO_HUP))
+ return FALSE;
+
+ fd = g_io_channel_unix_get_fd(channel);
+
+ result = read(fd, &si, sizeof(si));
+ if (result != sizeof(si))
+ return FALSE;
+
+ g_assert(test_data->expected_signal == si.ssi_signo);
+ context_quit(context);
+ return TRUE;
+}
+
+static guint setup_signalfd(gpointer user_data)
+{
+ GIOChannel *channel;
+ guint source;
+ sigset_t mask;
+ int ret;
+ int fd;
+
+ sigemptyset(&mask);
+ sigaddset(&mask, SIGINT);
+ sigaddset(&mask, SIGTERM);
+
+ ret = sigprocmask(SIG_BLOCK, &mask, NULL);
+ g_assert(ret == 0);
+
+ fd = signalfd(-1, &mask, 0);
+ g_assert(fd >= 0);
+
+ channel = g_io_channel_unix_new(fd);
+
+ g_io_channel_set_close_on_unref(channel, TRUE);
+ g_io_channel_set_encoding(channel, NULL, NULL);
+ g_io_channel_set_buffered(channel, FALSE);
+
+ source = g_io_add_watch(channel,
+ G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL,
+ signal_handler, user_data);
+
+ g_io_channel_unref(channel);
+
+ return source;
+}
+
+static struct context *create_context(gconstpointer data)
+{
+ struct context *context = g_new0(struct context, 1);
+ struct sockaddr_un addr;
+ GIOChannel *io;
+ int ret, sk;
+
+ context->main_loop = g_main_loop_new(NULL, FALSE);
+ g_assert(context->main_loop);
+
+ context->signal_source = setup_signalfd(context);
+ g_assert(context->signal_source);
+
+ sk = socket(AF_LOCAL, SOCK_SEQPACKET, 0);
+ g_assert(sk >= 0);
+
+ memset(&addr, 0, sizeof(addr));
+ addr.sun_family = AF_UNIX;
+
+ memcpy(addr.sun_path, BLUEZ_HAL_SK_PATH, sizeof(BLUEZ_HAL_SK_PATH));
+
+ ret = bind(sk, (struct sockaddr *) &addr, sizeof(addr));
+ g_assert(ret == 0);
+
+ ret = listen(sk, 5);
+ g_assert(ret == 0);
+
+ io = g_io_channel_unix_new(sk);
+
+ g_io_channel_set_close_on_unref(io, TRUE);
+
+ context->source = g_io_add_watch(io,
+ G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL,
+ connect_handler, context);
+ g_assert(context->source > 0);
+
+ g_io_channel_unref(io);
+
+ context->sk = sk;
+ context->data = data;
+
+ return context;
+}
+
+static void execute_context(struct context *context)
+{
+ g_main_loop_run(context->main_loop);
+
+ g_io_channel_shutdown(context->notif_io, true, NULL);
+ g_io_channel_shutdown(context->cmd_io, true, NULL);
+ g_io_channel_unref(context->cmd_io);
+ g_io_channel_unref(context->notif_io);
+
+ g_source_remove(context->notif_source);
+ g_source_remove(context->signal_source);
+ g_source_remove(context->cmd_source);
+ g_source_remove(context->source);
+
+ g_main_loop_unref(context->main_loop);
+
+ g_free(context);
+}
+
+static void test_init(gconstpointer data)
+{
+ struct context *context = create_context(data);
+
+ ipc_init();
+
+ execute_context(context);
+
+ ipc_cleanup();
+}
+
+static const struct test_data test_init_1 = {};
+
+int main(int argc, char *argv[])
+{
+ g_test_init(&argc, &argv, NULL);
+
+ if (g_test_verbose())
+ __btd_log_init("*", 0);
+
+ g_test_add_data_func("/android_ipc/init", &test_init_1, test_init);
+
+ return g_test_run();
+}
--
1.8.3.1
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [PATCHv3 2/5] android/ipc: Remove watches on cleanup
2014-01-16 10:04 [PATCHv3 1/5] android/unit: Add android IPC unit tests Marcin Kraglak
@ 2014-01-16 10:04 ` Marcin Kraglak
2014-01-16 10:05 ` [PATCHv3 3/5] android/unit: Add /android_ipc/send_cmd_1 test case Marcin Kraglak
` (3 subsequent siblings)
4 siblings, 0 replies; 6+ messages in thread
From: Marcin Kraglak @ 2014-01-16 10:04 UTC (permalink / raw)
To: linux-bluetooth
Remove watches on cleanup. It will avoid receiving
events after cleanup.
---
android/ipc.c | 17 +++++++++++++++--
1 file changed, 15 insertions(+), 2 deletions(-)
diff --git a/android/ipc.c b/android/ipc.c
index ed3ef3c..d6b96e3 100644
--- a/android/ipc.c
+++ b/android/ipc.c
@@ -45,6 +45,9 @@ static struct service_handler services[HAL_SERVICE_ID_MAX + 1];
static GIOChannel *cmd_io = NULL;
static GIOChannel *notif_io = NULL;
+static guint cmd_watch = 0;
+static guint notif_watch = 0;
+
int ipc_handle_msg(struct service_handler *handlers, size_t max_index,
const void *buf, ssize_t len)
{
@@ -192,11 +195,11 @@ static gboolean notif_connect_cb(GIOChannel *io, GIOCondition cond,
cond = G_IO_ERR | G_IO_HUP | G_IO_NVAL;
- g_io_add_watch(io, cond, notif_watch_cb, NULL);
+ notif_watch = g_io_add_watch(io, cond, notif_watch_cb, NULL);
cond = G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_NVAL;
- g_io_add_watch(cmd_io, cond, cmd_watch_cb, NULL);
+ cmd_watch = g_io_add_watch(cmd_io, cond, cmd_watch_cb, NULL);
info("IPC: successfully connected");
@@ -232,12 +235,22 @@ void ipc_init(void)
void ipc_cleanup(void)
{
+ if (cmd_watch) {
+ g_source_remove(cmd_watch);
+ cmd_watch = 0;
+ }
+
if (cmd_io) {
g_io_channel_shutdown(cmd_io, TRUE, NULL);
g_io_channel_unref(cmd_io);
cmd_io = NULL;
}
+ if (notif_watch) {
+ g_source_remove(notif_watch);
+ notif_watch = 0;
+ }
+
if (notif_io) {
g_io_channel_shutdown(notif_io, TRUE, NULL);
g_io_channel_unref(notif_io);
--
1.8.3.1
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [PATCHv3 3/5] android/unit: Add /android_ipc/send_cmd_1 test case
2014-01-16 10:04 [PATCHv3 1/5] android/unit: Add android IPC unit tests Marcin Kraglak
2014-01-16 10:04 ` [PATCHv3 2/5] android/ipc: Remove watches on cleanup Marcin Kraglak
@ 2014-01-16 10:05 ` Marcin Kraglak
2014-01-16 10:05 ` [PATCHv3 4/5] android/unit: Add /android_ipc/send_cmd_2 " Marcin Kraglak
` (2 subsequent siblings)
4 siblings, 0 replies; 6+ messages in thread
From: Marcin Kraglak @ 2014-01-16 10:05 UTC (permalink / raw)
To: linux-bluetooth
This test case will check if ipc lib will raise SIGTERM
after sending command to not registered service.
---
android/test-ipc.c | 46 +++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 45 insertions(+), 1 deletion(-)
diff --git a/android/test-ipc.c b/android/test-ipc.c
index 6ac1175..99f8559 100644
--- a/android/test-ipc.c
+++ b/android/test-ipc.c
@@ -44,6 +44,8 @@
struct test_data {
uint32_t expected_signal;
+ const struct hal_hdr *cmd;
+ uint16_t cmd_size;
};
struct context {
@@ -95,6 +97,7 @@ static gboolean connect_handler(GIOChannel *io, GIOCondition cond,
gpointer user_data)
{
struct context *context = user_data;
+ const struct test_data *test_data = context->data;
GIOChannel *new_io;
GIOCondition watch_cond;
int sk;
@@ -126,7 +129,7 @@ static gboolean connect_handler(GIOChannel *io, GIOCondition cond,
context->cmd_io = new_io;
}
- if (context->cmd_source && context->notif_source)
+ if (context->cmd_source && context->notif_source && !test_data->cmd)
context_quit(context);
return TRUE;
@@ -262,8 +265,48 @@ static void test_init(gconstpointer data)
ipc_cleanup();
}
+static gboolean send_cmd(gpointer user_data)
+{
+ struct context *context = user_data;
+ const struct test_data *test_data = context->data;
+ int sk;
+
+ sk = g_io_channel_unix_get_fd(context->cmd_io);
+ g_assert(sk >= 0);
+
+ g_assert(write(sk, test_data->cmd, test_data->cmd_size) ==
+ test_data->cmd_size);
+
+ return FALSE;
+}
+
+static void test_cmd(gconstpointer data)
+{
+ struct context *context = create_context(data);
+
+ ipc_init();
+
+ g_idle_add(send_cmd, context);
+
+ execute_context(context);
+
+ ipc_cleanup();
+}
+
static const struct test_data test_init_1 = {};
+static const struct hal_hdr test_cmd_1_hdr = {
+ .service_id = 0,
+ .opcode = 1,
+ .len = 0
+};
+
+static const struct test_data test_cmd_1 = {
+ .cmd = &test_cmd_1_hdr,
+ .cmd_size = sizeof(test_cmd_1_hdr),
+ .expected_signal = SIGTERM
+};
+
int main(int argc, char *argv[])
{
g_test_init(&argc, &argv, NULL);
@@ -272,6 +315,7 @@ int main(int argc, char *argv[])
__btd_log_init("*", 0);
g_test_add_data_func("/android_ipc/init", &test_init_1, test_init);
+ g_test_add_data_func("/android_ipc/send_cmd_1", &test_cmd_1, test_cmd);
return g_test_run();
}
--
1.8.3.1
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [PATCHv3 4/5] android/unit: Add /android_ipc/send_cmd_2 test case
2014-01-16 10:04 [PATCHv3 1/5] android/unit: Add android IPC unit tests Marcin Kraglak
2014-01-16 10:04 ` [PATCHv3 2/5] android/ipc: Remove watches on cleanup Marcin Kraglak
2014-01-16 10:05 ` [PATCHv3 3/5] android/unit: Add /android_ipc/send_cmd_1 test case Marcin Kraglak
@ 2014-01-16 10:05 ` Marcin Kraglak
2014-01-16 10:05 ` [PATCHv3 5/5] android/unit: Add /android_ipc/send_cmd_3 " Marcin Kraglak
2014-02-03 14:33 ` [PATCHv3 1/5] android/unit: Add android IPC unit tests Szymon Janc
4 siblings, 0 replies; 6+ messages in thread
From: Marcin Kraglak @ 2014-01-16 10:05 UTC (permalink / raw)
To: linux-bluetooth
This will test sending command to previously registered service.
---
android/test-ipc.c | 62 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 62 insertions(+)
diff --git a/android/test-ipc.c b/android/test-ipc.c
index 99f8559..930f9f4 100644
--- a/android/test-ipc.c
+++ b/android/test-ipc.c
@@ -46,6 +46,9 @@ struct test_data {
uint32_t expected_signal;
const struct hal_hdr *cmd;
uint16_t cmd_size;
+ uint8_t service;
+ const struct ipc_handler *handlers;
+ uint8_t handlers_size;
};
struct context {
@@ -74,11 +77,23 @@ static void context_quit(struct context *context)
static gboolean cmd_watch(GIOChannel *io, GIOCondition cond,
gpointer user_data)
{
+ struct context *context = user_data;
+ const struct test_data *test_data = context->data;
+ uint8_t buf[128];
+ int sk;
+
if (cond & (G_IO_HUP | G_IO_ERR | G_IO_NVAL)) {
g_assert(FALSE);
return FALSE;
}
+ sk = g_io_channel_unix_get_fd(io);
+
+ g_assert(read(sk, buf, sizeof(buf)) == test_data->cmd_size);
+ g_assert(!memcmp(test_data->cmd, buf, test_data->cmd_size));
+
+ context_quit(context);
+
return TRUE;
}
@@ -280,6 +295,17 @@ static gboolean send_cmd(gpointer user_data)
return FALSE;
}
+static gboolean register_service(gpointer user_data)
+{
+ struct context *context = user_data;
+ const struct test_data *test_data = context->data;
+
+ ipc_register(test_data->service, test_data->handlers,
+ test_data->handlers_size);
+
+ return FALSE;
+}
+
static void test_cmd(gconstpointer data)
{
struct context *context = create_context(data);
@@ -293,6 +319,28 @@ static void test_cmd(gconstpointer data)
ipc_cleanup();
}
+static void test_cmd_reg(gconstpointer data)
+{
+ struct context *context = create_context(data);
+ const struct test_data *test_data = context->data;
+
+ ipc_init();
+
+ g_idle_add(register_service, context);
+ g_idle_add(send_cmd, context);
+
+ execute_context(context);
+
+ ipc_unregister(test_data->service);
+
+ ipc_cleanup();
+}
+
+static void test_cmd_handler(const void *buf, uint16_t len)
+{
+ ipc_send_rsp(0, 1, 0);
+}
+
static const struct test_data test_init_1 = {};
static const struct hal_hdr test_cmd_1_hdr = {
@@ -307,6 +355,18 @@ static const struct test_data test_cmd_1 = {
.expected_signal = SIGTERM
};
+static const struct ipc_handler cmd_handlers[] = {
+ { test_cmd_handler, false, 0 }
+};
+
+static const struct test_data test_cmd_2 = {
+ .cmd = &test_cmd_1_hdr,
+ .cmd_size = sizeof(test_cmd_1_hdr),
+ .service = 0,
+ .handlers = cmd_handlers,
+ .handlers_size = 1
+};
+
int main(int argc, char *argv[])
{
g_test_init(&argc, &argv, NULL);
@@ -316,6 +376,8 @@ int main(int argc, char *argv[])
g_test_add_data_func("/android_ipc/init", &test_init_1, test_init);
g_test_add_data_func("/android_ipc/send_cmd_1", &test_cmd_1, test_cmd);
+ g_test_add_data_func("/android_ipc/send_cmd_2", &test_cmd_2,
+ test_cmd_reg);
return g_test_run();
}
--
1.8.3.1
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [PATCHv3 5/5] android/unit: Add /android_ipc/send_cmd_3 test case
2014-01-16 10:04 [PATCHv3 1/5] android/unit: Add android IPC unit tests Marcin Kraglak
` (2 preceding siblings ...)
2014-01-16 10:05 ` [PATCHv3 4/5] android/unit: Add /android_ipc/send_cmd_2 " Marcin Kraglak
@ 2014-01-16 10:05 ` Marcin Kraglak
2014-02-03 14:33 ` [PATCHv3 1/5] android/unit: Add android IPC unit tests Szymon Janc
4 siblings, 0 replies; 6+ messages in thread
From: Marcin Kraglak @ 2014-01-16 10:05 UTC (permalink / raw)
To: linux-bluetooth
This case will register service, next unregister it and send
command. Expected status is raise SIGTERM.
---
android/test-ipc.c | 36 ++++++++++++++++++++++++++++++++++++
1 file changed, 36 insertions(+)
diff --git a/android/test-ipc.c b/android/test-ipc.c
index 930f9f4..1fde61b 100644
--- a/android/test-ipc.c
+++ b/android/test-ipc.c
@@ -306,6 +306,16 @@ static gboolean register_service(gpointer user_data)
return FALSE;
}
+static gboolean unregister_service(gpointer user_data)
+{
+ struct context *context = user_data;
+ const struct test_data *test_data = context->data;
+
+ ipc_unregister(test_data->service);
+
+ return FALSE;
+}
+
static void test_cmd(gconstpointer data)
{
struct context *context = create_context(data);
@@ -336,6 +346,21 @@ static void test_cmd_reg(gconstpointer data)
ipc_cleanup();
}
+static void test_cmd_reg_1(gconstpointer data)
+{
+ struct context *context = create_context(data);
+
+ ipc_init();
+
+ g_idle_add(register_service, context);
+ g_idle_add(unregister_service, context);
+ g_idle_add(send_cmd, context);
+
+ execute_context(context);
+
+ ipc_cleanup();
+}
+
static void test_cmd_handler(const void *buf, uint16_t len)
{
ipc_send_rsp(0, 1, 0);
@@ -367,6 +392,15 @@ static const struct test_data test_cmd_2 = {
.handlers_size = 1
};
+static const struct test_data test_cmd_3 = {
+ .cmd = &test_cmd_1_hdr,
+ .cmd_size = sizeof(test_cmd_1_hdr),
+ .service = 0,
+ .handlers = cmd_handlers,
+ .handlers_size = 1,
+ .expected_signal = SIGTERM
+};
+
int main(int argc, char *argv[])
{
g_test_init(&argc, &argv, NULL);
@@ -378,6 +412,8 @@ int main(int argc, char *argv[])
g_test_add_data_func("/android_ipc/send_cmd_1", &test_cmd_1, test_cmd);
g_test_add_data_func("/android_ipc/send_cmd_2", &test_cmd_2,
test_cmd_reg);
+ g_test_add_data_func("/android_ipc/send_cmd_3", &test_cmd_3,
+ test_cmd_reg_1);
return g_test_run();
}
--
1.8.3.1
^ permalink raw reply related [flat|nested] 6+ messages in thread
* Re: [PATCHv3 1/5] android/unit: Add android IPC unit tests
2014-01-16 10:04 [PATCHv3 1/5] android/unit: Add android IPC unit tests Marcin Kraglak
` (3 preceding siblings ...)
2014-01-16 10:05 ` [PATCHv3 5/5] android/unit: Add /android_ipc/send_cmd_3 " Marcin Kraglak
@ 2014-02-03 14:33 ` Szymon Janc
4 siblings, 0 replies; 6+ messages in thread
From: Szymon Janc @ 2014-02-03 14:33 UTC (permalink / raw)
To: Marcin Kraglak; +Cc: linux-bluetooth
Hi Marcin,
On Thursday 16 of January 2014 11:04:58 Marcin Kraglak wrote:
> It will test ipc library. First test case will check
> ipc_init() call.
> ---
> .gitignore | 1 +
> android/Makefile.am | 8 ++
> android/test-ipc.c | 277 ++++++++++++++++++++++++++++++++++++++++++++++++++++
> 3 files changed, 286 insertions(+)
> create mode 100644 android/test-ipc.c
>
> diff --git a/.gitignore b/.gitignore
> index ac76fe2..ddd562a 100644
> --- a/.gitignore
> +++ b/.gitignore
> @@ -114,3 +114,4 @@ android/bluetoothd
> android/haltest
> android/android-tester
> android/bluetoothd-snoop
> +android/test-ipc
> diff --git a/android/Makefile.am b/android/Makefile.am
> index cd4a526..0c61317 100644
> --- a/android/Makefile.am
> +++ b/android/Makefile.am
> @@ -117,6 +117,14 @@ android_android_tester_LDADD = lib/libbluetooth-internal.la @GLIB_LIBS@
>
> android_android_tester_LDFLAGS = -pthread -ldl
>
> +noinst_PROGRAMS += android/test-ipc
> +
> +android_test_ipc_SOURCES = android/test-ipc.c \
> + src/shared/util.h src/shared/util.c \
> + src/log.h src/log.c \
> + android/ipc.c android/ipc.h
> +android_test_ipc_LDADD = @GLIB_LIBS@
> +
> plugin_LTLIBRARIES += android/audio.a2dp.default.la
>
> android_audio_a2dp_default_la_SOURCES = android/audio-msg.h \
> diff --git a/android/test-ipc.c b/android/test-ipc.c
> new file mode 100644
> index 0000000..6ac1175
> --- /dev/null
> +++ b/android/test-ipc.c
> @@ -0,0 +1,277 @@
> +/*
> + *
> + * BlueZ - Bluetooth protocol stack for Linux
> + *
> + * Copyright (C) 2014 Intel Corporation. All rights reserved.
> + *
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; either version 2 of the License, or
> + * (at your option) any later version.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program; if not, write to the Free Software
> + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
> + *
> + */
> +
> +#ifdef HAVE_CONFIG_H
> +#include <config.h>
> +#endif
> +#include <stdio.h>
> +#include <errno.h>
> +#include <unistd.h>
> +#include <stdlib.h>
> +#include <stdbool.h>
> +#include <inttypes.h>
> +#include <string.h>
> +#include <fcntl.h>
> +#include <sys/socket.h>
> +#include <sys/un.h>
> +#include <sys/signalfd.h>
> +
> +#include <glib.h>
> +#include "src/shared/util.h"
> +#include "src/log.h"
> +#include "android/hal-msg.h"
> +#include "android/ipc.h"
> +
> +struct test_data {
> + uint32_t expected_signal;
> +};
> +
> +struct context {
> + GMainLoop *main_loop;
> +
> + int sk;
> +
> + guint source;
> + guint cmd_source;
> + guint notif_source;
> +
> + GIOChannel *cmd_io;
> + GIOChannel *notif_io;
> + GIOChannel *signal_io;
> +
> + guint signal_source;
> +
> + const struct test_data *data;
> +};
> +
> +static void context_quit(struct context *context)
> +{
> + g_main_loop_quit(context->main_loop);
> +}
> +
> +static gboolean cmd_watch(GIOChannel *io, GIOCondition cond,
> + gpointer user_data)
> +{
> + if (cond & (G_IO_HUP | G_IO_ERR | G_IO_NVAL)) {
> + g_assert(FALSE);
> + return FALSE;
> + }
> +
> + return TRUE;
> +}
> +
> +static gboolean notif_watch(GIOChannel *io, GIOCondition cond,
> + gpointer user_data)
> +{
> + if (cond & (G_IO_HUP | G_IO_ERR | G_IO_NVAL)) {
> + g_assert(FALSE);
> + return FALSE;
> + }
> +
> + return TRUE;
> +}
> +
> +static gboolean connect_handler(GIOChannel *io, GIOCondition cond,
> + gpointer user_data)
> +{
> + struct context *context = user_data;
> + GIOChannel *new_io;
> + GIOCondition watch_cond;
> + int sk;
> +
> + if (cond & (G_IO_HUP | G_IO_ERR | G_IO_NVAL)) {
> + g_assert(FALSE);
> + return FALSE;
> + }
> +
> + g_assert(!context->cmd_source || !context->notif_source);
> +
> + sk = accept(context->sk, NULL, NULL);
> + g_assert(sk >= 0);
> +
> + new_io = g_io_channel_unix_new(sk);
> +
> + watch_cond = G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL;
> +
> + if (context->cmd_source && !context->notif_source) {
> + context->notif_source = g_io_add_watch(new_io, watch_cond,
> + notif_watch, context);
> + g_assert(context->notif_source > 0);
> + context->notif_io = new_io;
> + }
> +
> + if (!context->cmd_source) {
> + context->cmd_source = g_io_add_watch(new_io, watch_cond,
> + cmd_watch, context);
> + context->cmd_io = new_io;
> + }
> +
> + if (context->cmd_source && context->notif_source)
> + context_quit(context);
> +
> + return TRUE;
> +}
> +
> +static gboolean signal_handler(GIOChannel *channel, GIOCondition cond,
> + gpointer user_data)
> +{
> + struct context *context = user_data;
> + const struct test_data *test_data = context->data;
> + struct signalfd_siginfo si;
> + ssize_t result;
> + int fd;
> +
> + if (cond & (G_IO_NVAL | G_IO_ERR | G_IO_HUP))
> + return FALSE;
> +
> + fd = g_io_channel_unix_get_fd(channel);
> +
> + result = read(fd, &si, sizeof(si));
> + if (result != sizeof(si))
> + return FALSE;
> +
> + g_assert(test_data->expected_signal == si.ssi_signo);
> + context_quit(context);
> + return TRUE;
> +}
> +
> +static guint setup_signalfd(gpointer user_data)
> +{
> + GIOChannel *channel;
> + guint source;
> + sigset_t mask;
> + int ret;
> + int fd;
> +
> + sigemptyset(&mask);
> + sigaddset(&mask, SIGINT);
> + sigaddset(&mask, SIGTERM);
> +
> + ret = sigprocmask(SIG_BLOCK, &mask, NULL);
> + g_assert(ret == 0);
> +
> + fd = signalfd(-1, &mask, 0);
> + g_assert(fd >= 0);
> +
> + channel = g_io_channel_unix_new(fd);
> +
> + g_io_channel_set_close_on_unref(channel, TRUE);
> + g_io_channel_set_encoding(channel, NULL, NULL);
> + g_io_channel_set_buffered(channel, FALSE);
> +
> + source = g_io_add_watch(channel,
> + G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL,
> + signal_handler, user_data);
> +
> + g_io_channel_unref(channel);
> +
> + return source;
> +}
> +
> +static struct context *create_context(gconstpointer data)
> +{
> + struct context *context = g_new0(struct context, 1);
> + struct sockaddr_un addr;
> + GIOChannel *io;
> + int ret, sk;
> +
> + context->main_loop = g_main_loop_new(NULL, FALSE);
> + g_assert(context->main_loop);
> +
> + context->signal_source = setup_signalfd(context);
> + g_assert(context->signal_source);
> +
> + sk = socket(AF_LOCAL, SOCK_SEQPACKET, 0);
> + g_assert(sk >= 0);
> +
> + memset(&addr, 0, sizeof(addr));
> + addr.sun_family = AF_UNIX;
> +
> + memcpy(addr.sun_path, BLUEZ_HAL_SK_PATH, sizeof(BLUEZ_HAL_SK_PATH));
> +
> + ret = bind(sk, (struct sockaddr *) &addr, sizeof(addr));
> + g_assert(ret == 0);
> +
> + ret = listen(sk, 5);
> + g_assert(ret == 0);
> +
> + io = g_io_channel_unix_new(sk);
> +
> + g_io_channel_set_close_on_unref(io, TRUE);
> +
> + context->source = g_io_add_watch(io,
> + G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL,
> + connect_handler, context);
> + g_assert(context->source > 0);
> +
> + g_io_channel_unref(io);
> +
> + context->sk = sk;
> + context->data = data;
> +
> + return context;
> +}
> +
> +static void execute_context(struct context *context)
> +{
> + g_main_loop_run(context->main_loop);
> +
> + g_io_channel_shutdown(context->notif_io, true, NULL);
> + g_io_channel_shutdown(context->cmd_io, true, NULL);
> + g_io_channel_unref(context->cmd_io);
> + g_io_channel_unref(context->notif_io);
> +
> + g_source_remove(context->notif_source);
> + g_source_remove(context->signal_source);
> + g_source_remove(context->cmd_source);
> + g_source_remove(context->source);
> +
> + g_main_loop_unref(context->main_loop);
> +
> + g_free(context);
> +}
> +
> +static void test_init(gconstpointer data)
> +{
> + struct context *context = create_context(data);
> +
> + ipc_init();
> +
> + execute_context(context);
> +
> + ipc_cleanup();
> +}
> +
> +static const struct test_data test_init_1 = {};
> +
> +int main(int argc, char *argv[])
> +{
> + g_test_init(&argc, &argv, NULL);
> +
> + if (g_test_verbose())
> + __btd_log_init("*", 0);
> +
> + g_test_add_data_func("/android_ipc/init", &test_init_1, test_init);
> +
> + return g_test_run();
> +}
>
This is now applied (with some cleanups), thanks.
--
Best regards,
Szymon Janc
^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2014-02-03 14:33 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2014-01-16 10:04 [PATCHv3 1/5] android/unit: Add android IPC unit tests Marcin Kraglak
2014-01-16 10:04 ` [PATCHv3 2/5] android/ipc: Remove watches on cleanup Marcin Kraglak
2014-01-16 10:05 ` [PATCHv3 3/5] android/unit: Add /android_ipc/send_cmd_1 test case Marcin Kraglak
2014-01-16 10:05 ` [PATCHv3 4/5] android/unit: Add /android_ipc/send_cmd_2 " Marcin Kraglak
2014-01-16 10:05 ` [PATCHv3 5/5] android/unit: Add /android_ipc/send_cmd_3 " Marcin Kraglak
2014-02-03 14:33 ` [PATCHv3 1/5] android/unit: Add android IPC unit tests Szymon Janc
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).