/*
 * Copyright (c) 2017 Intel Corporation
 *
 * SPDX-License-Identifier: Apache-2.0
 */

#include "test_queue.h"

#define TIMEOUT K_MSEC(100)
#define STACK_SIZE (512 + CONFIG_TEST_EXTRA_STACK_SIZE)
#define LIST_LEN 2

static K_THREAD_STACK_DEFINE(tstack, STACK_SIZE);
static struct k_thread tdata;
K_SEM_DEFINE(sem, 0, 1);

/*test cases*/
/**
 * @brief Test k_queue_get() failure scenario
 * @ingroup kernel_queue_tests
 * @see k_queue_get()
 */
void test_queue_get_fail(void)
{
	static struct k_queue queue;

	k_queue_init(&queue);
	/**TESTPOINT: queue get returns NULL*/
	zassert_is_null(k_queue_get(&queue, K_NO_WAIT), NULL);
	zassert_is_null(k_queue_get(&queue, TIMEOUT), NULL);
}

/* The sub-thread entry */
static void tThread_entry(void *p1, void *p2, void *p3)
{
	k_sem_give(&sem);

	/* wait the queue for data */
	qdata_t *p = k_queue_get((struct k_queue *)p1, K_FOREVER);

	zassert_equal(p, p2, "Failed to append a unnormal list");
}

/**
 * @brief Test k_queue_append_list() failure scenario
 *
 * @details According to the API k_queue_append_list to
 * design some error condition to verify error branch of
 * the API.
 *	1. Verify that the list's head is empty.
 *	2. Verify that the list's tail is empty.
 *	3. Verify that append list to the queue when a
 * sub-thread is waiting for data.
 *
 * @ingroup kernel_queue_tests
 *
 * @see k_queue_append_list()
 */
void test_queue_append_list_error(void)
{
	static qdata_t data_l[2];
	static struct k_queue queue;
	static qdata_t *head = NULL, *tail = &data_l[1];

	k_queue_init(&queue);
	memset(data_l, 0, sizeof(data_l));

	/* Check if the list of head is equal to null */
	zassert_true(k_queue_append_list(&queue, (uint32_t *)head,
			(uint32_t *)tail) == -EINVAL,
			"failed to CHECKIF head == NULL");
	/* Check if the list of tail is equal to null */
	head = &data_l[0];
	tail = NULL;
	zassert_true(k_queue_append_list(&queue, (uint32_t *)head,
			(uint32_t *)tail) == -EINVAL,
			"failed to CHECKIF tail == NULL");
	/* Initializing the queue for re-using below */
	k_queue_init(&queue);

	/* Append unnormal list(just one node)into the queue for sub-thread */
	head = &data_l[0];
	head->snode.next = NULL;

	k_thread_create(&tdata, tstack, STACK_SIZE, tThread_entry, &queue,
			head, NULL, K_PRIO_PREEMPT(0), 0, K_NO_WAIT);
	/* Delay for thread initializing */
	k_sem_take(&sem, K_FOREVER);

	k_queue_append_list(&queue, (uint32_t *)head, (uint32_t *)head);

	k_thread_join(&tdata, K_FOREVER);
}

/**
 * @brief Test k_queue_merge_slist() failure scenario
 *
 * @details Verify the API k_queue_merge_slist when
 * a slist is empty or a slist's tail is null.
 *
 * @ingroup kernel_queue_tests
 *
 * @see k_queue_merge_slist()
 */
void test_queue_merge_list_error(void)
{
	qdata_t data_sl[2];
	static struct k_queue queue;
	sys_slist_t slist;

	k_queue_init(&queue);
	sys_slist_init(&slist);
	memset(data_sl, 0, sizeof(data_sl));

	/* Check if the slist is empty */
	zassert_true(k_queue_merge_slist(&queue, &slist) == -EINVAL,
			"Failed to CHECKIF slist is empty");
	/* Check if the tail of the slist is null */
	sys_slist_append(&slist, (sys_snode_t *)&(data_sl[0].snode));
	sys_slist_append(&slist, (sys_snode_t *)&(data_sl[1].snode));
	slist.tail = NULL;
	zassert_true(k_queue_merge_slist(&queue, &slist) != 0,
			"Failed to CHECKIF the tail of slist == null");
}

#ifdef CONFIG_USERSPACE
/**
 * @brief Test k_queue_init() failure scenario
 *
 * @details Verify that the parameter of API k_queue_init() is
 * NULL, what will happen.
 *
 * @ingroup kernel_queue_tests
 *
 * @see k_queue_init()
 */
void test_queue_init_null(void)
{
	ztest_set_fault_valid(true);
	k_queue_init(NULL);
}

/**
 * @brief Test k_queue_alloc_append() failure scenario
 *
 * @details Verify that the parameter of the API is
 * NULL, what will happen.
 *
 * @ingroup kernel_queue_tests
 *
 * @see k_queue_alloc_append()
 */
void test_queue_alloc_append_null(void)
{
	qdata_t data;

	memset(&data, 0, sizeof(data));
	ztest_set_fault_valid(true);
	k_queue_alloc_append(NULL, &data);
}

/**
 * @brief Test k_queue_alloc_prepend() failure scenario
 *
 * @details Verify that the parameter of the API is
 * NULL, what will happen.
 *
 * @ingroup kernel_queue_tests
 *
 * @see k_queue_alloc_prepend()
 */
void test_queue_alloc_prepend_null(void)
{
	qdata_t data;

	memset(&data, 0, sizeof(data));
	ztest_set_fault_valid(true);
	k_queue_alloc_prepend(NULL, &data);
}

/**
 * @brief Test k_queue_get() failure scenario
 *
 * @details Verify that the parameter of the API is
 * NULL, what will happen.
 *
 * @ingroup kernel_queue_tests
 *
 * @see k_queue_get()
 */
void test_queue_get_null(void)
{
	ztest_set_fault_valid(true);
	k_queue_get(NULL, K_FOREVER);
}

/**
 * @brief Test k_queue_is_empty() failure scenario
 *
 * @details Verify that the parameter of the API is
 * NULL, what will happen.
 *
 * @ingroup kernel_queue_tests
 *
 * @see k_queue_is_empty()
 */
void test_queue_is_empty_null(void)
{
	ztest_set_fault_valid(true);
	k_queue_is_empty(NULL);
}

/**
 * @brief Test k_queue_peek_head() failure scenario
 *
 * @details Verify that the parameter of the API is
 * NULL, what will happen.
 *
 * @ingroup kernel_queue_tests
 *
 * @see k_queue_peek_head()
 */
void test_queue_peek_head_null(void)
{
	ztest_set_fault_valid(true);
	k_queue_peek_head(NULL);
}

/**
 * @brief Test k_queue_peek_tail() failure scenario
 *
 * @details Verify that the parameter of the API is
 * NULL, what will happen.
 *
 * @ingroup kernel_queue_tests
 *
 * @see k_queue_peek_tail()
 */
void test_queue_peek_tail_null(void)
{
	ztest_set_fault_valid(true);
	k_queue_peek_tail(NULL);
}

/**
 * @brief Test k_queue_merge_slist() failure scenario
 *
 * @details Verify that the parameter of the API is
 * NULL, what will happen.
 *
 * @ingroup kernel_queue_tests
 *
 * @see k_queue_merge_slist()
 */
void test_queue_cancel_wait_error(void)
{
	struct k_queue *q;

	q = k_object_alloc(K_OBJ_QUEUE);
	zassert_not_null(q, "no memory for allocated queue object");
	k_queue_init(q);

	/* Check if cancel a qeueu that no thread to wait */
	k_queue_cancel_wait(q);

	/* Check if cancel a null pointer */
	ztest_set_fault_valid(true);
	k_queue_cancel_wait(NULL);
}

#endif /* CONFIG_USERSPACE */
