tests: mutex: Add test case to test mutex API

This test case tests posix mutex apis.

Signed-off-by: Punit Vara <punit.vara@intel.com>
diff --git a/tests/posix/mutex/CMakeLists.txt b/tests/posix/mutex/CMakeLists.txt
new file mode 100644
index 0000000..1f0f889
--- /dev/null
+++ b/tests/posix/mutex/CMakeLists.txt
@@ -0,0 +1,6 @@
+include($ENV{ZEPHYR_BASE}/cmake/app/boilerplate.cmake NO_POLICY_SCOPE)
+project(NONE)
+
+target_include_directories(app PRIVATE $ENV{ZEPHYR_BASE}/include/posix)
+FILE(GLOB app_sources src/*.c)
+target_sources(app PRIVATE ${app_sources})
diff --git a/tests/posix/mutex/prj.conf b/tests/posix/mutex/prj.conf
new file mode 100644
index 0000000..97e4323
--- /dev/null
+++ b/tests/posix/mutex/prj.conf
@@ -0,0 +1,2 @@
+CONFIG_PTHREAD_IPC=y
+CONFIG_ZTEST=y
diff --git a/tests/posix/mutex/src/posix_mutex.c b/tests/posix/mutex/src/posix_mutex.c
new file mode 100644
index 0000000..3d3e0b9
--- /dev/null
+++ b/tests/posix/mutex/src/posix_mutex.c
@@ -0,0 +1,171 @@
+/*
+ * Copyright (c) 2018 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <ztest.h>
+#include <errno.h>
+#include <pthread.h>
+
+#define STACK_SIZE (1024 + CONFIG_TEST_EXTRA_STACKSIZE)
+
+static K_THREAD_STACK_DEFINE(stack, STACK_SIZE);
+
+#define SLEEP_MS 100
+
+pthread_mutex_t mutex1;
+pthread_mutex_t mutex2;
+
+void *normal_mutex_entry(void *p1)
+{
+	int i, rc;
+
+	/* Sleep for maximum 300 ms as main thread is sleeping for 100 ms */
+
+	for (i = 0; i < 3; i++) {
+		rc = pthread_mutex_trylock(&mutex1);
+		if (rc == 0) {
+			break;
+		}
+		k_sleep(SLEEP_MS);
+	}
+
+	zassert_false(rc, "try lock failed");
+	TC_PRINT("mutex lock is taken\n");
+	zassert_false(pthread_mutex_unlock(&mutex1),
+		      "mutex unlock is falied");
+	return NULL;
+}
+
+void *recursive_mutex_entry(void *p1)
+{
+	zassert_false(pthread_mutex_lock(&mutex2), "mutex is not taken");
+	zassert_false(pthread_mutex_lock(&mutex2),
+		      "mutex is not taken 2nd time");
+	TC_PRINT("recrusive mutex lock is taken\n");
+	zassert_false(pthread_mutex_unlock(&mutex2),
+		      "mutex is not unlocked");
+	zassert_false(pthread_mutex_unlock(&mutex2),
+		      "mutex is not unlocked");
+	return NULL;
+}
+
+/**
+ * @brief Test to demostrate PTHREAD_MUTEX_NORMAL
+ *
+ * @details Mutex type is setup as normal. pthread_mutex_trylock
+ *	    and pthread_mutex_lock are tested with mutex type being
+ *	    normal.
+ */
+static void test_mutex_normal(void)
+{
+	pthread_t thread_1;
+	pthread_attr_t attr;
+	pthread_mutexattr_t mut_attr;
+	struct sched_param schedparam;
+	int schedpolicy = SCHED_FIFO;
+	int ret, type, protocol, temp;
+
+	schedparam.priority = 2;
+	ret = pthread_attr_init(&attr);
+	if (ret != 0) {
+		zassert_false(pthread_attr_destroy(&attr),
+			      "Unable to destroy pthread object attrib");
+		zassert_false(pthread_attr_init(&attr),
+			      "Unable to create pthread object attrib");
+	}
+
+	pthread_attr_setstack(&attr, &stack, STACK_SIZE);
+	pthread_attr_setschedpolicy(&attr, schedpolicy);
+	pthread_attr_setschedparam(&attr, &schedparam);
+
+	temp = pthread_mutexattr_settype(&mut_attr, PTHREAD_MUTEX_NORMAL);
+	zassert_false(temp, "setting mutex type is failed");
+	temp = pthread_mutex_init(&mutex1, &mut_attr);
+	zassert_false(temp, "mutex initialization is failed");
+
+	temp = pthread_mutexattr_gettype(&mut_attr, &type);
+	zassert_false(temp, "reading mutex type is failed");
+	temp = pthread_mutexattr_getprotocol(&mut_attr, &protocol);
+	zassert_false(temp, "reading mutex protocol is failed");
+
+	pthread_mutex_lock(&mutex1);
+
+	zassert_equal(type, PTHREAD_MUTEX_NORMAL,
+		      "mutex type is not normal");
+
+	zassert_equal(protocol, PTHREAD_PRIO_NONE,
+		      "mutex protocol is not prio_none");
+	ret = pthread_create(&thread_1, &attr, &normal_mutex_entry, NULL);
+
+	if (ret) {
+		TC_PRINT("Thread1 creation failed %d", ret);
+	}
+	k_sleep(SLEEP_MS);
+	pthread_mutex_unlock(&mutex1);
+
+	pthread_join(thread_1, NULL);
+	temp = pthread_mutex_destroy(&mutex1);
+	zassert_false(temp, "Destroying mutex is failed");
+}
+
+/**
+ * @brief Test to demostrate PTHREAD_MUTEX_RECURSIVE
+ *
+ * @details Mutex type is setup as recursive. mutex will be locked
+ *	    twice and unlocked for the same number of time.
+ *
+ */
+static void test_recursive_mutex(void)
+{
+	pthread_t thread_2;
+	pthread_attr_t attr2;
+	pthread_mutexattr_t mut_attr2;
+	struct sched_param schedparam2;
+	int schedpolicy = SCHED_FIFO;
+	int ret, type, protocol, temp;
+
+	schedparam2.priority = 2;
+	ret = pthread_attr_init(&attr2);
+	if (ret != 0) {
+		zassert_false(pthread_attr_destroy(&attr2),
+			      "Unable to destroy pthread object attrib");
+		zassert_false(pthread_attr_init(&attr2),
+			      "Unable to create pthread object attrib");
+	}
+
+	pthread_attr_setstack(&attr2, &stack, STACK_SIZE);
+	pthread_attr_setschedpolicy(&attr2, schedpolicy);
+	pthread_attr_setschedparam(&attr2, &schedparam2);
+
+	temp = pthread_mutexattr_settype(&mut_attr2, PTHREAD_MUTEX_RECURSIVE);
+	zassert_false(temp, "setting mutex2 type is failed");
+	temp = pthread_mutex_init(&mutex2, &mut_attr2);
+	zassert_false(temp, "mutex2 initialization is failed");
+
+	temp = pthread_mutexattr_gettype(&mut_attr2, &type);
+	zassert_false(temp, "reading mutex2 type is failed");
+	temp = pthread_mutexattr_getprotocol(&mut_attr2, &protocol);
+	zassert_false(temp, "reading mutex2 protocol is failed");
+
+	zassert_equal(type, PTHREAD_MUTEX_RECURSIVE,
+		      "mutex2 type is not recursive");
+
+	zassert_equal(protocol, PTHREAD_PRIO_NONE,
+		      "mutex2 protocol is not prio_none");
+	ret = pthread_create(&thread_2, &attr2, &recursive_mutex_entry, NULL);
+
+	zassert_false(ret, "Thread2 creation failed");
+
+	pthread_join(thread_2, NULL);
+	temp = pthread_mutex_destroy(&mutex2);
+	zassert_false(temp, "Destroying mutex2 is failed");
+}
+
+void test_main(void)
+{
+	ztest_test_suite(test_mutex, ztest_unit_test(test_mutex_normal),
+			ztest_unit_test(test_recursive_mutex));
+	ztest_run_test_suite(test_mutex);
+}
diff --git a/tests/posix/mutex/testcase.yaml b/tests/posix/mutex/testcase.yaml
new file mode 100644
index 0000000..6a43091
--- /dev/null
+++ b/tests/posix/mutex/testcase.yaml
@@ -0,0 +1,5 @@
+tests:
+  posix.mutex:
+    arch_exclude: nios2 riscv32
+    tags: core
+