2014-01-14 12:14:37

by Jakub Tyszkowski

[permalink] [raw]
Subject: [PATCHv2 0/8] IPC negative tester

Following patchset adds IPC negative tester framework with few test cases
checking IPC's behaviour on daemon side. Expected daemon's behaviour is to
shut down gracefully in case of receiving invalid IPC data.

V2 changes:
* fixed few indentation issues
* fixed missing __attribute__((packed))
* fixed amount of data written for 'malformed data' test case
* fixed opcode for 'invalid service' test case
* added patch(8) with more 'malformed data' cases

Jakub Tyszkowski (8):
android/ipc-tester: Skeleton for ipc negative tester
android/ipc-tester: Run daemon in separate process
android/ipc-tester: Add IPC initialization
android/ipc-tester: Add daemon shutdown handler
android/ipc-tester: Add sending test data with ipc
android/ipc-tester: Register services
android/ipc-tester: Add basic negative test cases for IPC's daemon
site
androi/ipc-tester: Add more cases for malformed data

.gitignore | 1 +
android/Makefile.am | 17 +
android/ipc-negative-tester.c | 721 ++++++++++++++++++++++++++++++++++++++++++
3 files changed, 739 insertions(+)
create mode 100644 android/ipc-negative-tester.c

--
1.8.5.2



2014-01-14 12:14:45

by Jakub Tyszkowski

[permalink] [raw]
Subject: [PATCHv2 8/8] androi/ipc-tester: Add more cases for malformed data

This patch adds tests for more types of possible data malformations.
---
android/ipc-negative-tester.c | 46 +++++++++++++++++++++++++++++++++++++++++++
1 file changed, 46 insertions(+)

diff --git a/android/ipc-negative-tester.c b/android/ipc-negative-tester.c
index 8ec3308..cac7f59 100644
--- a/android/ipc-negative-tester.c
+++ b/android/ipc-negative-tester.c
@@ -585,6 +585,48 @@ static const struct generic_data malformed_data = {
.num_services = 1,
};

+static const struct generic_data malformed_data2 = {
+ .ipc_data = {
+ /* use proper msg */
+ .buffer = &register_bt_msg,
+ /* but write incomplete */
+ .len = sizeof(register_bt_msg) - 1,
+ },
+ .init_services = {HAL_SERVICE_ID_BLUETOOTH},
+ .num_services = 1,
+};
+
+struct malformed_data3_struct {
+ struct regmod_msg valid_msg;
+ int redundant_data;
+} __attribute__((packed));
+
+static struct malformed_data3_struct malformed_data3_msg = {
+ /* valid register service message */
+ .valid_msg = {
+ .header = {
+ .service_id = HAL_SERVICE_ID_CORE,
+ .opcode = HAL_OP_REGISTER_MODULE,
+ .len = sizeof(struct hal_cmd_register_module),
+ },
+ .cmd = {
+ .service_id = HAL_SERVICE_ID_CORE,
+ },
+ },
+ /* plus redundant data */
+ . redundant_data = 666,
+};
+
+static const struct generic_data malformed_data3 = {
+ .ipc_data = {
+ /* use malformed msg */
+ .buffer = &malformed_data3_msg,
+ .len = sizeof(malformed_data3_msg),
+ },
+ .init_services = {HAL_SERVICE_ID_BLUETOOTH},
+ .num_services = 1,
+};
+
struct hal_hdr enable_unknown_service_hdr = {
.service_id = HAL_SERVICE_ID_MAX + 1,
.opcode = HAL_OP_REGISTER_MODULE,
@@ -661,6 +703,10 @@ int main(int argc, char *argv[])
setup, ipc_send_tc, teardown);
test_bredrle("Malformed data (wrong payload declared)", &malformed_data,
setup, ipc_send_tc, teardown);
+ test_bredrle("Malformed data2 (undersized msg)", &malformed_data2,
+ setup, ipc_send_tc, teardown);
+ test_bredrle("Malformed data3 (oversized msg)", &malformed_data3,
+ setup, ipc_send_tc, teardown);
test_bredrle("Invalid service", &enable_unknown_service_data,
setup, ipc_send_tc, teardown);
test_bredrle("Enable unregistered service",
--
1.8.5.2


2014-01-14 12:14:44

by Jakub Tyszkowski

[permalink] [raw]
Subject: [PATCHv2 7/8] android/ipc-tester: Add basic negative test cases for IPC's daemon site

This patch add first few test cases checking for proper daemon
termination in case of receiving invalid IPC data.
---
android/ipc-negative-tester.c | 120 ++++++++++++++++++++++++++++++++++++++++--
1 file changed, 117 insertions(+), 3 deletions(-)

diff --git a/android/ipc-negative-tester.c b/android/ipc-negative-tester.c
index a5b05cb..8ec3308 100644
--- a/android/ipc-negative-tester.c
+++ b/android/ipc-negative-tester.c
@@ -540,22 +540,136 @@ static void ipc_send_tc(const void *data)
3, user, g_free); \
} while (0)

-static const struct generic_data dummy_data = {
+struct regmod_msg register_bt_msg = {
+ .header = {
+ .service_id = HAL_SERVICE_ID_CORE,
+ .opcode = HAL_OP_REGISTER_MODULE,
+ .len = sizeof(struct hal_cmd_register_module),
+ },
+ .cmd = {
+ .service_id = HAL_SERVICE_ID_CORE,
+ },
+};
+
+static const struct generic_data to_small_data = {
.ipc_data = {
- .buffer = "",
+ /* valid header and payload */
+ .buffer = &register_bt_msg,
+ /* but write only incomplete header */
.len = 1,
},
.init_services = {HAL_SERVICE_ID_BLUETOOTH},
.num_services = 1,
};

+struct regmod_msg register_bt_malformed_size_msg = {
+ .header = {
+ .service_id = HAL_SERVICE_ID_CORE,
+ .opcode = HAL_OP_REGISTER_MODULE,
+ /* wrong payload size declared */
+ .len = sizeof(struct hal_cmd_register_module) - 1,
+ },
+ .cmd = {
+ .service_id = HAL_SERVICE_ID_CORE,
+ },
+};
+
+static const struct generic_data malformed_data = {
+ .ipc_data = {
+ /* use malformed msg - wrong size declared */
+ .buffer = &register_bt_malformed_size_msg,
+ /* but write proper size */
+ .len = sizeof(register_bt_malformed_size_msg),
+ },
+ .init_services = {HAL_SERVICE_ID_BLUETOOTH},
+ .num_services = 1,
+};
+
+struct hal_hdr enable_unknown_service_hdr = {
+ .service_id = HAL_SERVICE_ID_MAX + 1,
+ .opcode = HAL_OP_REGISTER_MODULE,
+ .len = 0,
+};
+
+static const struct generic_data enable_unknown_service_data = {
+ .ipc_data = {
+ /* enable invalid service */
+ .buffer = &enable_unknown_service_hdr,
+ .len = sizeof(enable_unknown_service_hdr),
+ },
+ .init_services = {HAL_SERVICE_ID_BLUETOOTH},
+ .num_services = 1,
+};
+
+struct hal_hdr enable_bt_service_hdr = {
+ .service_id = HAL_SERVICE_ID_BLUETOOTH,
+ .opcode = HAL_OP_ENABLE,
+ .len = 0,
+};
+
+static const struct generic_data enable_unregistered_service_data = {
+ .ipc_data = {
+ /* valid msg */
+ .buffer = &enable_bt_service_hdr,
+ /* send the whole thing */
+ .len = sizeof(enable_bt_service_hdr),
+ },
+ /* but don't register it before enabling */
+ .init_services = {},
+ .num_services = 0,
+};
+
+struct hal_hdr invalid_opcode_hdr = {
+ .service_id = HAL_SERVICE_ID_BLUETOOTH,
+ .opcode = 0x16,
+ .len = 0,
+};
+
+static const struct generic_data invalid_opcode_data = {
+ .ipc_data = {
+ /* valid msg */
+ .buffer = &invalid_opcode_hdr,
+ /* send the whole thing */
+ .len = sizeof(invalid_opcode_hdr),
+ },
+ .init_services = {HAL_SERVICE_ID_BLUETOOTH},
+ .num_services = 1,
+};
+
+struct hal_hdr invalid_msg_size_hdr = {
+ .service_id = HAL_SERVICE_ID_BLUETOOTH,
+ .opcode = HAL_OP_CREATE_BOND,
+ .len = 0,
+};
+
+static const struct generic_data invalid_msg_size_data = {
+ .ipc_data = {
+ .buffer = &invalid_msg_size_hdr,
+ .len = sizeof(invalid_msg_size_hdr),
+ },
+ .init_services = {HAL_SERVICE_ID_BLUETOOTH},
+ .num_services = 1,
+};
+
int main(int argc, char *argv[])
{
snprintf(exec_dir, sizeof(exec_dir), "%s", dirname(argv[0]));

tester_init(&argc, &argv);

- test_bredrle("Test Dummy", &dummy_data, setup, ipc_send_tc, teardown);
+ test_bredrle("To small data", &to_small_data,
+ setup, ipc_send_tc, teardown);
+ test_bredrle("Malformed data (wrong payload declared)", &malformed_data,
+ setup, ipc_send_tc, teardown);
+ test_bredrle("Invalid service", &enable_unknown_service_data,
+ setup, ipc_send_tc, teardown);
+ test_bredrle("Enable unregistered service",
+ &enable_unregistered_service_data,
+ setup, ipc_send_tc, teardown);
+ test_bredrle("Invalid opcode", &invalid_opcode_data,
+ setup, ipc_send_tc, teardown);
+ test_bredrle("Invalid msg size for opcode", &invalid_msg_size_data,
+ setup, ipc_send_tc, teardown);

return tester_run();
}
--
1.8.5.2


2014-01-14 12:14:43

by Jakub Tyszkowski

[permalink] [raw]
Subject: [PATCHv2 6/8] android/ipc-tester: Register services

This patch adds basic bluetooth service registration during setup procedure.
Without this daemon would reject commands for not registered services.
---
android/ipc-negative-tester.c | 48 ++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 47 insertions(+), 1 deletion(-)

diff --git a/android/ipc-negative-tester.c b/android/ipc-negative-tester.c
index 46a8754..a5b05cb 100644
--- a/android/ipc-negative-tester.c
+++ b/android/ipc-negative-tester.c
@@ -404,13 +404,53 @@ failed:
return false;
}

+struct regmod_msg {
+ struct hal_hdr header;
+ struct hal_cmd_register_module cmd;
+} __attribute__((packed));
+
+static bool setup_module(int service_id)
+{
+ struct hal_hdr response;
+ struct hal_hdr expected_response;
+
+ struct regmod_msg btmodule_msg = {
+ .header = {
+ .service_id = HAL_SERVICE_ID_CORE,
+ .opcode = HAL_OP_REGISTER_MODULE,
+ .len = sizeof(struct hal_cmd_register_module),
+ },
+ .cmd = {
+ .service_id = service_id,
+ },
+ };
+
+ if (write(cmd_sk, &btmodule_msg, sizeof(btmodule_msg)) < 0)
+ goto fail;
+
+ if (read(cmd_sk, &response, sizeof(response)) < 0)
+ goto fail;
+
+ expected_response = btmodule_msg.header;
+ expected_response.len = 0;
+
+ if (memcmp(&response, &expected_response, sizeof(response)) == 0)
+ return true;
+
+fail:
+ tester_warn("Module registration failed.");
+ return false;
+}
+
static void setup(const void *data)
{
+ const struct generic_data *generic_data = data;
struct test_data *test_data = tester_get_data();
int signal_fd[2];
char buf[1024];
pid_t pid;
int len;
+ unsigned int i;

if (pipe(signal_fd)) {
tester_setup_failed();
@@ -454,9 +494,15 @@ static void setup(const void *data)
return;
}

- /* TODO: register modules */
+ tester_print("Will init %d services.", generic_data->num_services);
+
+ for (i = 0; i < generic_data->num_services; i++)
+ if (!setup_module(generic_data->init_services[i]))
+ tester_setup_failed();

test_data->setup_done = true;
+
+ tester_setup_complete();
}

static void teardown(const void *data)
--
1.8.5.2


2014-01-14 12:14:42

by Jakub Tyszkowski

[permalink] [raw]
Subject: [PATCHv2 5/8] android/ipc-tester: Add sending test data with ipc

This patch adds some data structures used to send data with ipc during test setup
and run stage.
---
android/ipc-negative-tester.c | 30 +++++++++++++++++++++++++++++-
1 file changed, 29 insertions(+), 1 deletion(-)

diff --git a/android/ipc-negative-tester.c b/android/ipc-negative-tester.c
index bbe4ce6..46a8754 100644
--- a/android/ipc-negative-tester.c
+++ b/android/ipc-negative-tester.c
@@ -49,6 +49,18 @@ struct test_data {
bool setup_done;
};

+struct ipc_data {
+ void *buffer;
+ size_t len;
+};
+
+struct generic_data {
+ struct ipc_data ipc_data;
+
+ unsigned int num_services;
+ int init_services[];
+};
+
#define CONNECT_TIMEOUT (5 * 1000)
#define SERVICE_NAME "bluetoothd"

@@ -461,6 +473,13 @@ static void teardown(const void *data)

static void ipc_send_tc(const void *data)
{
+ const struct generic_data *generic_data = data;
+ const struct ipc_data *ipc_data = &generic_data->ipc_data;
+
+ if (ipc_data->len) {
+ if (write(cmd_sk, ipc_data->buffer, ipc_data->len) < 0)
+ tester_test_failed();
+ }
}

#define test_bredrle(name, data, test_setup, test, test_teardown) \
@@ -475,13 +494,22 @@ static void ipc_send_tc(const void *data)
3, user, g_free); \
} while (0)

+static const struct generic_data dummy_data = {
+ .ipc_data = {
+ .buffer = "",
+ .len = 1,
+ },
+ .init_services = {HAL_SERVICE_ID_BLUETOOTH},
+ .num_services = 1,
+};
+
int main(int argc, char *argv[])
{
snprintf(exec_dir, sizeof(exec_dir), "%s", dirname(argv[0]));

tester_init(&argc, &argv);

- test_bredrle("Test Dummy", NULL, setup, ipc_send_tc, teardown);
+ test_bredrle("Test Dummy", &dummy_data, setup, ipc_send_tc, teardown);

return tester_run();
}
--
1.8.5.2


2014-01-14 12:14:40

by Jakub Tyszkowski

[permalink] [raw]
Subject: [PATCHv2 3/8] android/ipc-tester: Add IPC initialization

This patch adds IPC mechanism initialization.
The deamon is being started and IPC socket connection is established.
---
android/ipc-negative-tester.c | 122 ++++++++++++++++++++++++++++++++++++++++++
1 file changed, 122 insertions(+)

diff --git a/android/ipc-negative-tester.c b/android/ipc-negative-tester.c
index 78ca104..1736794 100644
--- a/android/ipc-negative-tester.c
+++ b/android/ipc-negative-tester.c
@@ -17,6 +17,8 @@

#include <stdlib.h>
#include <unistd.h>
+#include <errno.h>
+#include <poll.h>

#include <sys/socket.h>
#include <sys/types.h>
@@ -32,6 +34,8 @@
#include "src/shared/mgmt.h"
#include "src/shared/hciemu.h"

+#include "hal-msg.h"
+#include <cutils/properties.h>

#define WAIT_FOR_SIGNAL_TIME 2 /* in seconds */
#define EMULATOR_SIGNAL "emulator_started"
@@ -44,8 +48,14 @@ struct test_data {
pid_t bluetoothd_pid;
};

+#define CONNECT_TIMEOUT (5 * 1000)
+#define SERVICE_NAME "bluetoothd"
+
static char exec_dir[PATH_MAX + 1];

+static int cmd_sk = -1;
+static int notif_sk = -1;
+
static void read_info_callback(uint8_t status, uint16_t length,
const void *param, void *user_data)
{
@@ -240,6 +250,109 @@ failed:
close(fd);
}

+static int accept_connection(int sk)
+{
+ int err;
+ struct pollfd pfd;
+ int new_sk;
+
+ memset(&pfd, 0 , sizeof(pfd));
+ pfd.fd = sk;
+ pfd.events = POLLIN;
+
+ err = poll(&pfd, 1, CONNECT_TIMEOUT);
+ if (err < 0) {
+ err = errno;
+ tester_warn("Failed to poll: %d (%s)", err, strerror(err));
+ return -errno;
+ }
+
+ if (err == 0) {
+ tester_warn("bluetoothd connect timeout");
+ return -errno;
+ }
+
+ new_sk = accept(sk, NULL, NULL);
+ if (new_sk < 0) {
+ err = errno;
+ tester_warn("Failed to accept socket: %d (%s)",
+ err, strerror(err));
+ return -errno;
+ }
+
+ return new_sk;
+}
+
+static bool init_ipc(void)
+{
+ struct sockaddr_un addr;
+
+ int sk;
+ int err;
+
+ sk = socket(AF_LOCAL, SOCK_SEQPACKET, 0);
+ if (sk < 0) {
+ err = errno;
+ tester_warn("Failed to create socket: %d (%s)", err,
+ strerror(err));
+ return false;
+ }
+
+ memset(&addr, 0, sizeof(addr));
+ addr.sun_family = AF_UNIX;
+
+ memcpy(addr.sun_path, BLUEZ_HAL_SK_PATH, sizeof(BLUEZ_HAL_SK_PATH));
+
+ if (bind(sk, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
+ err = errno;
+ tester_warn("Failed to bind socket: %d (%s)", err,
+ strerror(err));
+ close(sk);
+ return false;
+ }
+
+ if (listen(sk, 2) < 0) {
+ err = errno;
+ tester_warn("Failed to listen on socket: %d (%s)", err,
+ strerror(err));
+ close(sk);
+ return false;
+ }
+
+ /* Start Android Bluetooth daemon service */
+ if (property_set("ctl.start", SERVICE_NAME) < 0) {
+ tester_warn("Failed to start service %s", SERVICE_NAME);
+ close(sk);
+ return false;
+ }
+
+ cmd_sk = accept_connection(sk);
+ if (cmd_sk < 0) {
+ close(sk);
+ return false;
+ }
+
+ notif_sk = accept_connection(sk);
+ if (notif_sk < 0) {
+ close(sk);
+ close(cmd_sk);
+ cmd_sk = -1;
+ return false;
+ }
+
+ tester_print("bluetoothd connected");
+
+ close(sk);
+
+ return true;
+}
+
+static void cleanup_ipc(void)
+{
+ close(cmd_sk);
+ cmd_sk = -1;
+}
+
static void setup(const void *data)
{
struct test_data *test_data = tester_get_data();
@@ -280,12 +393,21 @@ static void setup(const void *data)
tester_setup_failed();
return;
}
+ if (!init_ipc()) {
+ tester_warn("Cannot initialize IPC mechanism!");
+ tester_setup_failed();
+ return;
+ }
+
+ /* TODO: register modules */
}

static void teardown(const void *data)
{
struct test_data *test_data = tester_get_data();

+ cleanup_ipc();
+
if (test_data->bluetoothd_pid)
waitpid(test_data->bluetoothd_pid, NULL, 0);

--
1.8.5.2


2014-01-14 12:14:41

by Jakub Tyszkowski

[permalink] [raw]
Subject: [PATCHv2 4/8] android/ipc-tester: Add daemon shutdown handler

Handle daemon shutdown asynchronously.
---
android/ipc-negative-tester.c | 45 +++++++++++++++++++++++++++++++++++++++++++
1 file changed, 45 insertions(+)

diff --git a/android/ipc-negative-tester.c b/android/ipc-negative-tester.c
index 1736794..bbe4ce6 100644
--- a/android/ipc-negative-tester.c
+++ b/android/ipc-negative-tester.c
@@ -46,6 +46,7 @@ struct test_data {
struct hciemu *hciemu;
enum hciemu_type hciemu_type;
pid_t bluetoothd_pid;
+ bool setup_done;
};

#define CONNECT_TIMEOUT (5 * 1000)
@@ -353,6 +354,44 @@ static void cleanup_ipc(void)
cmd_sk = -1;
}

+static gboolean check_for_daemon(gpointer user_data)
+{
+ int status;
+ struct test_data *data = user_data;
+
+ if ((waitpid(data->bluetoothd_pid, &status, WNOHANG))
+ != data->bluetoothd_pid)
+ return true;
+
+ if (WIFEXITED(status)) {
+ tester_test_passed();
+ } else if (WIFSIGNALED(status)) {
+ switch (WTERMSIG(status)) {
+ case SIGTERM:
+ if (data->setup_done)
+ tester_test_passed();
+ else
+ tester_setup_failed();
+ break;
+ case SIGSEGV:
+ tester_warn("Daemon died with segmentation fault");
+ goto failed;
+ default:
+ tester_warn("Bad signal received %d", status);
+ goto failed;
+ }
+ }
+
+ return true;
+
+failed:
+ if (data->setup_done)
+ tester_test_failed();
+ else
+ tester_setup_failed();
+ return false;
+}
+
static void setup(const void *data)
{
struct test_data *test_data = tester_get_data();
@@ -393,6 +432,10 @@ static void setup(const void *data)
tester_setup_failed();
return;
}
+
+ g_idle_add_full(G_PRIORITY_DEFAULT_IDLE, check_for_daemon, test_data,
+ NULL);
+
if (!init_ipc()) {
tester_warn("Cannot initialize IPC mechanism!");
tester_setup_failed();
@@ -400,6 +443,8 @@ static void setup(const void *data)
}

/* TODO: register modules */
+
+ test_data->setup_done = true;
}

static void teardown(const void *data)
--
1.8.5.2


2014-01-14 12:14:39

by Jakub Tyszkowski

[permalink] [raw]
Subject: [PATCHv2 2/8] android/ipc-tester: Run daemon in separate process

This patch adds new process waiting to run daemon when needed.
---
android/ipc-negative-tester.c | 124 +++++++++++++++++++++++++++++++++++++++++-
1 file changed, 123 insertions(+), 1 deletion(-)

diff --git a/android/ipc-negative-tester.c b/android/ipc-negative-tester.c
index 0c2edda..78ca104 100644
--- a/android/ipc-negative-tester.c
+++ b/android/ipc-negative-tester.c
@@ -15,8 +15,14 @@
*
*/

+#include <stdlib.h>
#include <unistd.h>

+#include <sys/socket.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <sys/un.h>
+#include <libgen.h>
#include <glib.h>

#include "lib/bluetooth.h"
@@ -27,13 +33,19 @@
#include "src/shared/hciemu.h"


+#define WAIT_FOR_SIGNAL_TIME 2 /* in seconds */
+#define EMULATOR_SIGNAL "emulator_started"
+
struct test_data {
struct mgmt *mgmt;
uint16_t mgmt_index;
struct hciemu *hciemu;
enum hciemu_type hciemu_type;
+ pid_t bluetoothd_pid;
};

+static char exec_dir[PATH_MAX + 1];
+
static void read_info_callback(uint8_t status, uint16_t length,
const void *param, void *user_data)
{
@@ -162,13 +174,121 @@ static void test_post_teardown(const void *data)
test_data->hciemu = NULL;
}

+static void bluetoothd_start(int hci_index)
+{
+ char prg_name[PATH_MAX + 1];
+ char index[8];
+ char *prg_argv[4];
+
+ snprintf(prg_name, sizeof(prg_name), "%s/%s", exec_dir, "bluetoothd");
+ snprintf(index, sizeof(index), "%d", hci_index);
+
+ prg_argv[0] = prg_name;
+ prg_argv[1] = "-i";
+ prg_argv[2] = index;
+ prg_argv[3] = NULL;
+
+ if (!tester_use_debug())
+ fclose(stderr);
+
+ execve(prg_argv[0], prg_argv, NULL);
+}
+
+static void emulator(int pipe, int hci_index)
+{
+ static const char SYSTEM_SOCKET_PATH[] = "\0android_system";
+ char buf[1024];
+ struct sockaddr_un addr;
+ struct timeval tv;
+ int fd;
+ ssize_t len;
+
+ fd = socket(PF_LOCAL, SOCK_DGRAM | SOCK_CLOEXEC, 0);
+ if (fd < 0)
+ goto failed;
+
+ tv.tv_sec = WAIT_FOR_SIGNAL_TIME;
+ tv.tv_usec = 0;
+ setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, (char *)&tv, sizeof(tv));
+
+ memset(&addr, 0, sizeof(addr));
+ addr.sun_family = AF_UNIX;
+ memcpy(addr.sun_path, SYSTEM_SOCKET_PATH, sizeof(SYSTEM_SOCKET_PATH));
+
+ if (bind(fd, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
+ perror("Failed to bind system socket");
+ goto failed;
+ }
+
+ len = write(pipe, EMULATOR_SIGNAL, sizeof(EMULATOR_SIGNAL));
+
+ if (len != sizeof(EMULATOR_SIGNAL))
+ goto failed;
+
+ memset(buf, 0, sizeof(buf));
+
+ len = read(fd, buf, sizeof(buf));
+ if (len <= 0 || (strcmp(buf, "ctl.start=bluetoothd")))
+ goto failed;
+
+ close(pipe);
+ close(fd);
+ bluetoothd_start(hci_index);
+
+failed:
+ close(pipe);
+ close(fd);
+}
+
static void setup(const void *data)
{
- tester_setup_failed();
+ struct test_data *test_data = tester_get_data();
+ int signal_fd[2];
+ char buf[1024];
+ pid_t pid;
+ int len;
+
+ if (pipe(signal_fd)) {
+ tester_setup_failed();
+ return;
+ }
+
+ pid = fork();
+
+ if (pid < 0) {
+ close(signal_fd[0]);
+ close(signal_fd[1]);
+ tester_setup_failed();
+ return;
+ }
+
+ if (pid == 0) {
+ if (!tester_use_debug())
+ fclose(stderr);
+
+ close(signal_fd[0]);
+ emulator(signal_fd[1], test_data->mgmt_index);
+ exit(0);
+ }
+
+ close(signal_fd[1]);
+ test_data->bluetoothd_pid = pid;
+
+ len = read(signal_fd[0], buf, sizeof(buf));
+ if (len <= 0 || (strcmp(buf, EMULATOR_SIGNAL))) {
+ close(signal_fd[0]);
+ tester_setup_failed();
+ return;
+ }
}

static void teardown(const void *data)
{
+ struct test_data *test_data = tester_get_data();
+
+ if (test_data->bluetoothd_pid)
+ waitpid(test_data->bluetoothd_pid, NULL, 0);
+
tester_teardown_complete();
}

@@ -190,6 +310,8 @@ static void ipc_send_tc(const void *data)

int main(int argc, char *argv[])
{
+ snprintf(exec_dir, sizeof(exec_dir), "%s", dirname(argv[0]));
+
tester_init(&argc, &argv);

test_bredrle("Test Dummy", NULL, setup, ipc_send_tc, teardown);
--
1.8.5.2


2014-01-14 12:14:38

by Jakub Tyszkowski

[permalink] [raw]
Subject: [PATCHv2 1/8] android/ipc-tester: Skeleton for ipc negative tester

Add skeleton for ipc negative testing.
---
.gitignore | 1 +
android/Makefile.am | 17 ++++
android/ipc-negative-tester.c | 198 ++++++++++++++++++++++++++++++++++++++++++
3 files changed, 216 insertions(+)
create mode 100644 android/ipc-negative-tester.c

diff --git a/.gitignore b/.gitignore
index ac76fe2..d790fd2 100644
--- a/.gitignore
+++ b/.gitignore
@@ -113,4 +113,5 @@ android/system-emulator
android/bluetoothd
android/haltest
android/android-tester
+android/ipc-negative-tester
android/bluetoothd-snoop
diff --git a/android/Makefile.am b/android/Makefile.am
index 356f932..c89c7e3 100644
--- a/android/Makefile.am
+++ b/android/Makefile.am
@@ -121,6 +121,23 @@ android_android_tester_LDFLAGS = -pthread -ldl

plugin_LTLIBRARIES += android/audio.a2dp.default.la

+noinst_PROGRAMS += android/ipc-negative-tester
+
+android_ipc_negative_tester_SOURCES = emulator/btdev.h emulator/btdev.c \
+ emulator/bthost.h emulator/bthost.c \
+ src/shared/io.h src/shared/io-glib.c \
+ src/shared/queue.h src/shared/queue.c \
+ src/shared/util.h src/shared/util.c \
+ src/shared/mgmt.h src/shared/mgmt.c \
+ src/shared/hciemu.h src/shared/hciemu.c \
+ src/shared/tester.h src/shared/tester.c \
+ android/hal-utils.h android/hal-utils.c \
+ android/ipc-negative-tester.c
+
+android_ipc_negative_tester_CFLAGS = $(AM_CFLAGS) -I$(srcdir)/android
+
+android_ipc_negative_tester_LDADD = lib/libbluetooth-internal.la @GLIB_LIBS@
+
android_audio_a2dp_default_la_SOURCES = android/audio-msg.h \
android/hal-audio.c \
android/hardware/audio.h \
diff --git a/android/ipc-negative-tester.c b/android/ipc-negative-tester.c
new file mode 100644
index 0000000..0c2edda
--- /dev/null
+++ b/android/ipc-negative-tester.c
@@ -0,0 +1,198 @@
+/*
+ * Copyright (C) 2014 Intel Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <unistd.h>
+
+#include <glib.h>
+
+#include "lib/bluetooth.h"
+#include "lib/mgmt.h"
+
+#include "src/shared/tester.h"
+#include "src/shared/mgmt.h"
+#include "src/shared/hciemu.h"
+
+
+struct test_data {
+ struct mgmt *mgmt;
+ uint16_t mgmt_index;
+ struct hciemu *hciemu;
+ enum hciemu_type hciemu_type;
+};
+
+static void read_info_callback(uint8_t status, uint16_t length,
+ const void *param, void *user_data)
+{
+ struct test_data *data = tester_get_data();
+ const struct mgmt_rp_read_info *rp = param;
+ char addr[18];
+ uint16_t manufacturer;
+ uint32_t supported_settings, current_settings;
+
+ tester_print("Read Info callback");
+ tester_print(" Status: 0x%02x", status);
+
+ if (status || !param) {
+ tester_pre_setup_failed();
+ return;
+ }
+
+ ba2str(&rp->bdaddr, addr);
+ manufacturer = btohs(rp->manufacturer);
+ supported_settings = btohl(rp->supported_settings);
+ current_settings = btohl(rp->current_settings);
+
+ tester_print(" Address: %s", addr);
+ tester_print(" Version: 0x%02x", rp->version);
+ tester_print(" Manufacturer: 0x%04x", manufacturer);
+ tester_print(" Supported settings: 0x%08x", supported_settings);
+ tester_print(" Current settings: 0x%08x", current_settings);
+ tester_print(" Class: 0x%02x%02x%02x",
+ rp->dev_class[2], rp->dev_class[1], rp->dev_class[0]);
+ tester_print(" Name: %s", rp->name);
+ tester_print(" Short name: %s", rp->short_name);
+
+ if (strcmp(hciemu_get_address(data->hciemu), addr)) {
+ tester_pre_setup_failed();
+ return;
+ }
+
+ tester_pre_setup_complete();
+}
+
+static void index_added_callback(uint16_t index, uint16_t length,
+ const void *param, void *user_data)
+{
+ struct test_data *data = tester_get_data();
+
+ tester_print("Index Added callback");
+ tester_print(" Index: 0x%04x", index);
+
+ data->mgmt_index = index;
+
+ mgmt_send(data->mgmt, MGMT_OP_READ_INFO, data->mgmt_index, 0, NULL,
+ read_info_callback, NULL, NULL);
+}
+
+static void index_removed_callback(uint16_t index, uint16_t length,
+ const void *param, void *user_data)
+{
+ struct test_data *data = tester_get_data();
+
+ tester_print("Index Removed callback");
+ tester_print(" Index: 0x%04x", index);
+
+ if (index != data->mgmt_index)
+ return;
+
+ mgmt_unregister_index(data->mgmt, data->mgmt_index);
+
+ mgmt_unref(data->mgmt);
+ data->mgmt = NULL;
+
+ tester_post_teardown_complete();
+}
+
+static void read_index_list_callback(uint8_t status, uint16_t length,
+ const void *param, void *user_data)
+{
+ struct test_data *data = tester_get_data();
+
+ tester_print("Read Index List callback");
+ tester_print(" Status: 0x%02x", status);
+
+ if (status || !param) {
+ tester_pre_setup_failed();
+ return;
+ }
+
+ mgmt_register(data->mgmt, MGMT_EV_INDEX_ADDED, MGMT_INDEX_NONE,
+ index_added_callback, NULL, NULL);
+
+ mgmt_register(data->mgmt, MGMT_EV_INDEX_REMOVED, MGMT_INDEX_NONE,
+ index_removed_callback, NULL, NULL);
+
+ data->hciemu = hciemu_new(data->hciemu_type);
+ if (!data->hciemu) {
+ tester_warn("Failed to setup HCI emulation");
+ tester_pre_setup_failed();
+ return;
+ }
+
+ tester_print("New hciemu instance created");
+}
+
+static void test_pre_setup(const void *data)
+{
+ struct test_data *test_data = tester_get_data();
+
+ if (!tester_use_debug())
+ fclose(stderr);
+
+ test_data->mgmt = mgmt_new_default();
+ if (!test_data->mgmt) {
+ tester_warn("Failed to setup management interface");
+ tester_pre_setup_failed();
+ return;
+ }
+
+ mgmt_send(test_data->mgmt, MGMT_OP_READ_INDEX_LIST, MGMT_INDEX_NONE, 0,
+ NULL, read_index_list_callback, NULL, NULL);
+}
+
+static void test_post_teardown(const void *data)
+{
+ struct test_data *test_data = tester_get_data();
+
+ hciemu_unref(test_data->hciemu);
+ test_data->hciemu = NULL;
+}
+
+static void setup(const void *data)
+{
+ tester_setup_failed();
+}
+
+static void teardown(const void *data)
+{
+ tester_teardown_complete();
+}
+
+static void ipc_send_tc(const void *data)
+{
+}
+
+#define test_bredrle(name, data, test_setup, test, test_teardown) \
+ do { \
+ struct test_data *user; \
+ user = g_malloc0(sizeof(struct test_data)); \
+ if (!user) \
+ break; \
+ user->hciemu_type = HCIEMU_TYPE_BREDRLE; \
+ tester_add_full(name, data, test_pre_setup, test_setup, \
+ test, test_teardown, test_post_teardown, \
+ 3, user, g_free); \
+ } while (0)
+
+int main(int argc, char *argv[])
+{
+ tester_init(&argc, &argv);
+
+ test_bredrle("Test Dummy", NULL, setup, ipc_send_tc, teardown);
+
+ return tester_run();
+}
--
1.8.5.2