[PATCH 08/11] android/test: Add HAL IPC disconnect tests

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



---
 android/test-hal-ipc.c | 122 +++++++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 117 insertions(+), 5 deletions(-)

diff --git a/android/test-hal-ipc.c b/android/test-hal-ipc.c
index b4cf071..bc86a3e 100644
--- a/android/test-hal-ipc.c
+++ b/android/test-hal-ipc.c
@@ -34,15 +34,51 @@
 #include <sys/un.h>
 #include <sys/wait.h>
 #include <errno.h>
+#include <pthread.h>
 
 #include <glib.h>
 #include "android/ipc-common.h"
 #include "android/hal-ipc.h"
 
 static const char HAL_SK_PATH[] = "\0test_hal_ipc_socket";
+static int cmd_sk = -1;
+static int notif_sk = -1;
+
+static void disconnect_hal(bool cmd_first)
+{
+	int sk1, sk2;
+
+	if (cmd_first) {
+		sk1 = cmd_sk;
+		sk2 = notif_sk;
+	} else {
+		sk1 = notif_sk;
+		sk2 = cmd_sk;
+	}
+
+	if (sk1 >= 0) {
+		shutdown(sk1, SHUT_RDWR);
+		close(sk1);
+	}
+
+	if (sk2 >= 0) {
+		shutdown(sk2, SHUT_RDWR);
+		close(sk2);
+	}
+
+	cmd_sk = -1;
+	notif_sk = -1;
+}
+
+static void cleanup_hal(void)
+{
+	disconnect_hal(true);
+}
 
 static void test_init(void)
 {
+	cleanup_hal();
+
 	g_assert(hal_ipc_init(HAL_SK_PATH, sizeof(HAL_SK_PATH)));
 
 	hal_ipc_cleanup();
@@ -55,25 +91,26 @@ static void test_init(void)
 static void connect_hal(void)
 {
 	struct sockaddr_un addr;
-	int sk;
 
 	memset(&addr, 0, sizeof(addr));
 	addr.sun_family = AF_UNIX;
 
 	memcpy(addr.sun_path, HAL_SK_PATH, sizeof(HAL_SK_PATH));
 
-	sk = socket(AF_LOCAL, SOCK_SEQPACKET, 0);
+	cmd_sk = socket(AF_LOCAL, SOCK_SEQPACKET, 0);
 
-	connect(sk, (struct sockaddr *) &addr, sizeof(addr));
+	connect(cmd_sk, (struct sockaddr *) &addr, sizeof(addr));
 
-	sk = socket(AF_LOCAL, SOCK_SEQPACKET, 0);
-	connect(sk, (struct sockaddr *) &addr, sizeof(addr));
+	notif_sk = socket(AF_LOCAL, SOCK_SEQPACKET, 0);
+	connect(notif_sk, (struct sockaddr *) &addr, sizeof(addr));
 }
 
 static void test_accept(void)
 {
 	pid_t pid;
 
+	cleanup_hal();
+
 	g_assert(hal_ipc_init(HAL_SK_PATH, sizeof(HAL_SK_PATH)));
 
 	pid = fork();
@@ -127,6 +164,73 @@ static void test_thread_cb(void)
 	thread_cb_cnt = 0;
 }
 
+static pthread_mutex_t cv_mutex = PTHREAD_MUTEX_INITIALIZER;
+static pthread_cond_t cv = PTHREAD_COND_INITIALIZER;
+static bool disconnected = false;
+
+static void disconnect_cb(void *data)
+{
+	disconnected = true;
+
+	pthread_mutex_lock(&cv_mutex);
+	pthread_cond_signal(&cv);
+	pthread_mutex_unlock(&cv_mutex);
+}
+
+static void test_disconnect(const void *data)
+{
+	pid_t pid;
+	bool cmd_first = (bool) data;
+	struct timespec ts;
+
+	cleanup_hal();
+
+	g_assert(hal_ipc_init(HAL_SK_PATH, sizeof(HAL_SK_PATH)));
+
+	pid = fork();
+	if (pid == 0) {
+		connect_hal();
+		disconnect_hal(cmd_first);
+		exit(0);
+	}
+
+	g_assert(pid > 0);
+
+	hal_ipc_set_disconnect_cb(disconnect_cb, NULL);
+
+	pthread_mutex_lock(&cv_mutex);
+
+	g_assert(hal_ipc_accept());
+
+	wait(NULL);
+
+	clock_gettime(CLOCK_REALTIME, &ts);
+	ts.tv_sec += 15;
+
+	/*
+	 * This is not needed in real usecase but here we want to test if
+	 * disconnect callback was properly called on socket shutdown so
+	 * we need to wait until it happen before calling cleanup (otherwise
+	 * we might have a race where cleanup is called before notif thread is
+	 * scheduled resulting in clean shutdown
+	 */
+	g_assert(pthread_cond_timedwait(&cv, &cv_mutex, &ts) == 0);
+	pthread_mutex_unlock(&cv_mutex);
+
+	hal_ipc_cleanup();
+
+	g_assert(disconnected);
+	disconnected = false;
+}
+
+static void test_disconnect_stress(const void *data)
+{
+	int i;
+
+	for (i = 0; i < 9999; i++)
+		test_disconnect(data);
+}
+
 int main(int argc, char *argv[])
 {
 	g_test_init(&argc, &argv, NULL);
@@ -137,6 +241,14 @@ int main(int argc, char *argv[])
 	g_test_add_func("/android_hal_ipc/init", test_init);
 	g_test_add_func("/android_hal_ipc/accept", test_accept);
 	g_test_add_func("/android_hal_ipc/thread_cb", test_thread_cb);
+	g_test_add_data_func("/android_hal_ipc/disconnect1", (void *) true,
+							test_disconnect);
+	g_test_add_data_func("/android_hal_ipc/disconnect1_stress",
+					(void *) true, test_disconnect_stress);
+	g_test_add_data_func("/android_hal_ipc/disconnect2", (void *) false,
+							test_disconnect);
+	g_test_add_data_func("/android_hal_ipc/disconnect2_stress",
+					(void *) false, test_disconnect_stress);
 
 	return g_test_run();
 }
-- 
1.9.3

--
To unsubscribe from this list: send the line "unsubscribe linux-bluetooth" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html




[Index of Archives]     [Bluez Devel]     [Linux Wireless Networking]     [Linux Wireless Personal Area Networking]     [Linux ATH6KL]     [Linux USB Devel]     [Linux Media Drivers]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Big List of Linux Books]

  Powered by Linux