Linux Audio

Check our new training course

Embedded Linux Audio

Check our new training course
with Creative Commons CC-BY-SA
lecture materials

Bootlin logo

Elixir Cross Referencer

Loading...
/*
 * Copyright (c) 2020 Intel Corporation
 *
 * SPDX-License-Identifier: Apache-2.0
 */
#include <ztest.h>
#include <irq_offload.h>
#include <ztest_error_hook.h>

#define STACK_SIZE (512 + CONFIG_TEST_EXTRA_STACKSIZE)
#define THREAD_TEST_PRIORITY 5

/* use to pass case type to threads */
static ZTEST_DMEM int case_type;

static struct k_mutex mutex;
static struct k_sem sem;
static struct k_pipe pipe;
static struct k_queue queue;


static K_THREAD_STACK_DEFINE(tstack, STACK_SIZE);
static struct k_thread tdata;

/* enumerate our negative case scenario */
enum {
	MUTEX_INIT_NULL,
	MUTEX_INIT_INVALID_OBJ,
	MUTEX_LOCK_NULL,
	MUTEX_LOCK_INVALID_OBJ,
	MUTEX_UNLOCK_NULL,
	MUTEX_UNLOCK_INVALID_OBJ,
	NOT_DEFINE
} neg_case;

/* This is a semaphore using inside irq_offload */
extern struct k_sem offload_sem;

/* A call back function which is hooked in default assert handler. */
void ztest_post_fatal_error_hook(unsigned int reason,
		const z_arch_esf_t *pEsf)

{
	/* check if expected error */
	zassert_equal(reason, K_ERR_KERNEL_OOPS, NULL);
}

static void tThread_entry_negative(void *p1, void *p2, void *p3)
{
	int choice = *((int *)p2);

	TC_PRINT("current case is %d\n", choice);

	/* Set up the fault or assert are expected before we call
	 * the target tested funciton.
	 */
	switch (choice) {
	case MUTEX_INIT_NULL:
		ztest_set_fault_valid(true);
		k_mutex_init(NULL);
		break;
	case MUTEX_INIT_INVALID_OBJ:
		ztest_set_fault_valid(true);
		k_mutex_init((struct k_mutex *)&sem);
		break;
	case MUTEX_LOCK_NULL:
		ztest_set_fault_valid(true);
		k_mutex_lock(NULL, K_NO_WAIT);
		break;
	case MUTEX_LOCK_INVALID_OBJ:
		ztest_set_fault_valid(true);
		k_mutex_lock((struct k_mutex *)&pipe, K_NO_WAIT);
		break;
	case MUTEX_UNLOCK_NULL:
		ztest_set_fault_valid(true);
		k_mutex_unlock(NULL);
		break;
	case MUTEX_UNLOCK_INVALID_OBJ:
		ztest_set_fault_valid(true);
		k_mutex_unlock((struct k_mutex *)&queue);
		break;
	default:
		TC_PRINT("should not be here!\n");
		break;
	}

	/* If negative comes here, it means error condition not been
	 * detected.
	 */
	ztest_test_fail();
}

static int create_negative_test_thread(int choice)
{
	int ret;
	uint32_t perm = K_INHERIT_PERMS;

	if (_is_user_context()) {
		perm = perm | K_USER;
	}

	case_type = choice;

	k_tid_t tid = k_thread_create(&tdata, tstack, STACK_SIZE,
			(k_thread_entry_t)tThread_entry_negative,
			&mutex, (void *)&case_type, NULL,
			K_PRIO_PREEMPT(THREAD_TEST_PRIORITY),
			perm, K_NO_WAIT);

	ret = k_thread_join(tid, K_FOREVER);

	return ret;
}


/**
 * @brief Test initializing mutex with a NULL pointer
 *
 * @details Pass a null pointer as parameter, then see if the
 * expected error happens.
 *
 * @ingroup kernel_mutex_tests
 *
 * @see k_mutex_init()
 */
static void test_mutex_init_null(void)
{
	create_negative_test_thread(MUTEX_INIT_NULL);
}

/**
 * @brief Test initialize mutex with a invalid kernel object
 *
 * @details Pass a invalid kobject as parameter, then see if the
 * expected error happens.
 *
 * @ingroup kernel_mutex_tests
 *
 * @see k_mutex_init()
 */
static void test_mutex_init_invalid_obj(void)
{
	create_negative_test_thread(MUTEX_INIT_INVALID_OBJ);
}

/**
 * @brief Test locking mutex with a NULL pointer
 *
 * @details Pass a null pointer as parameter, then see if the
 * expected error happens.
 *
 * @ingroup kernel_mutex_tests
 *
 * @see k_mutex_lock()
 */
static void test_mutex_lock_null(void)
{
	create_negative_test_thread(MUTEX_LOCK_NULL);
}

/**
 * @brief Test locking mutex with a invalid kernel object
 *
 * @details Pass a invalid kobject as parameter, then see if the
 * expected error happens.
 *
 * @ingroup kernel_mutex_tests
 *
 * @see k_mutex_lock()
 */
/* TESTPOINT: Pass a invalid kobject into the API k_mutex_lock */
static void test_mutex_lock_invalid_obj(void)
{
	create_negative_test_thread(MUTEX_LOCK_INVALID_OBJ);
}

/**
 * @brief Test unlocking mutex with a NULL pointer
 *
 * @details Pass a null pointer as parameter, then see if the
 * expected error happens.
 *
 * @ingroup kernel_mutex_tests
 *
 * @see k_mutex_unlock()
 */
static void test_mutex_unlock_null(void)
{
	create_negative_test_thread(MUTEX_UNLOCK_NULL);
}

/**
 * @brief Test unlocking mutex with a invalid kernel object
 *
 * @details Pass a invalid kobject as parameter, then see if the
 * expected error happens.
 *
 * @ingroup kernel_mutex_tests
 *
 * @see k_mutex_unlock()
 */
/* TESTPOINT: Pass a invalid kobject into the API k_mutex_unlock */
static void test_mutex_unlock_invalid_obj(void)
{
	create_negative_test_thread(MUTEX_UNLOCK_INVALID_OBJ);
}

/*test case main entry*/
void test_main(void)
{
	k_thread_access_grant(k_current_get(), &tdata, &tstack,
		       &mutex, &sem, &pipe, &queue);

	ztest_test_suite(mutex_api,
		 ztest_user_unit_test(test_mutex_init_null),
		 ztest_user_unit_test(test_mutex_init_invalid_obj),
		 ztest_user_unit_test(test_mutex_lock_null),
		 ztest_user_unit_test(test_mutex_lock_invalid_obj),
		 ztest_user_unit_test(test_mutex_unlock_null),
		 ztest_user_unit_test(test_mutex_unlock_invalid_obj)
		 );
	ztest_run_test_suite(mutex_api);
}