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

/**
 * @addtogroup t_mbox
 * @{
 * @defgroup t_mbox_api test_mbox_api
 * @brief TestPurpose: verify data passing via mailbox APIs
 * - API coverage
 *   -# K_MBOX_DEFINE
 *   -# k_mbox_init
 *   -# k_mbox_put
 *   -# k_mbox_async_put
 *   -# k_mbox_get
 *   -# k_mbox_data_get
 *   -# k_mbox_data_block_get
 * @}
 */

#include <ztest.h>

#define TIMEOUT 100
#define STACK_SIZE (512 + CONFIG_TEST_EXTRA_STACKSIZE)
#define MAIL_LEN 64


/**TESTPOINT: init via K_MBOX_DEFINE*/
K_MBOX_DEFINE(kmbox);
K_MEM_POOL_DEFINE(mpooltx, 8, MAIL_LEN, 1, 4);
K_MEM_POOL_DEFINE(mpoolrx, 8, MAIL_LEN, 1, 4);

static struct k_mbox mbox;

static k_tid_t sender_tid, receiver_tid;

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

static struct k_sem end_sema, sync_sema;

static enum mmsg_type {
	PUT_GET_NULL = 0,
	PUT_GET_BUFFER,
	ASYNC_PUT_GET_BUFFER,
	ASYNC_PUT_GET_BLOCK,
	TARGET_SOURCE_THREAD_BUFFER,
	TARGET_SOURCE_THREAD_BLOCK,
	MAX_INFO_TYPE
} info_type;

static char data[MAX_INFO_TYPE][MAIL_LEN] = {
	"send/recv an empty message",
	"send/recv msg using a buffer",
	"async send/recv msg using a buffer",
	"async send/recv msg using a memory block",
	"specify target/source thread, using a buffer",
	"specify target/source thread, using a memory block"
};

static void tmbox_put(struct k_mbox *pmbox)
{
	struct k_mbox_msg mmsg;

	memset(&mmsg, 0, sizeof(mmsg));

	switch (info_type) {
	case PUT_GET_NULL:
		/**TESTPOINT: mbox sync put empty message*/
		mmsg.info = PUT_GET_NULL;
		mmsg.size = 0;
		mmsg.tx_data = NULL;
		mmsg.tx_target_thread = K_ANY;
		k_mbox_put(pmbox, &mmsg, K_FOREVER);
		break;
	case PUT_GET_BUFFER:
	/*fall through*/
	case TARGET_SOURCE_THREAD_BUFFER:
		/**TESTPOINT: mbox sync put buffer*/
		mmsg.info = PUT_GET_BUFFER;
		mmsg.size = sizeof(data[info_type]);
		mmsg.tx_data = data[info_type];
		if (info_type == TARGET_SOURCE_THREAD_BUFFER) {
			mmsg.tx_target_thread = receiver_tid;
		} else {
			mmsg.tx_target_thread = K_ANY;
		}
		k_mbox_put(pmbox, &mmsg, K_FOREVER);
		break;
	case ASYNC_PUT_GET_BUFFER:
		/**TESTPOINT: mbox async put buffer*/
		mmsg.info = ASYNC_PUT_GET_BUFFER;
		mmsg.size = sizeof(data[info_type]);
		mmsg.tx_data = data[info_type];
		mmsg.tx_target_thread = K_ANY;
		k_mbox_async_put(pmbox, &mmsg, &sync_sema);
		/*wait for msg being taken*/
		k_sem_take(&sync_sema, K_FOREVER);
		break;
	case ASYNC_PUT_GET_BLOCK:
	/*fall through*/
	case TARGET_SOURCE_THREAD_BLOCK:
		/**TESTPOINT: mbox async put mem block*/
		mmsg.info = ASYNC_PUT_GET_BLOCK;
		mmsg.size = MAIL_LEN;
		mmsg.tx_data = NULL;
		zassert_equal(k_mem_pool_alloc(&mpooltx, &mmsg.tx_block,
					       MAIL_LEN, K_NO_WAIT), 0, NULL);
		memcpy(mmsg.tx_block.data, data[info_type], MAIL_LEN);
		if (info_type == TARGET_SOURCE_THREAD_BLOCK) {
			mmsg.tx_target_thread = receiver_tid;
		} else {
			mmsg.tx_target_thread = K_ANY;
		}
		k_mbox_async_put(pmbox, &mmsg, &sync_sema);
		/*wait for msg being taken*/
		k_sem_take(&sync_sema, K_FOREVER);
		break;
	default:
		break;
	}
}

static void tmbox_get(struct k_mbox *pmbox)
{
	struct k_mbox_msg mmsg;
	char rxdata[MAIL_LEN];
	struct k_mem_block rxblock;

	switch (info_type) {
	case PUT_GET_NULL:
		/**TESTPOINT: mbox sync get buffer*/
		mmsg.size = sizeof(rxdata);
		mmsg.rx_source_thread = K_ANY;
		/*verify return value*/
		zassert_true(k_mbox_get(pmbox, &mmsg, rxdata, K_FOREVER) == 0,
			     NULL);
		/*verify .info*/
		zassert_equal(mmsg.info, PUT_GET_NULL, NULL);
		/*verify .size*/
		zassert_equal(mmsg.size, 0, NULL);
		break;
	case PUT_GET_BUFFER:
	/*fall through*/
	case TARGET_SOURCE_THREAD_BUFFER:
		/**TESTPOINT: mbox sync get buffer*/
		mmsg.size = sizeof(rxdata);
		if (info_type == TARGET_SOURCE_THREAD_BUFFER) {
			mmsg.rx_source_thread = sender_tid;
		} else {
			mmsg.rx_source_thread = K_ANY;
		}
		zassert_true(k_mbox_get(pmbox, &mmsg, rxdata, K_FOREVER) == 0,
			     NULL);
		zassert_equal(mmsg.info, PUT_GET_BUFFER, NULL);
		zassert_equal(mmsg.size, sizeof(data[info_type]), NULL);
		/*verify rxdata*/
		zassert_true(memcmp(rxdata, data[info_type], MAIL_LEN) == 0,
			     NULL);
		break;
	case ASYNC_PUT_GET_BUFFER:
		/**TESTPOINT: mbox async get buffer*/
		mmsg.size = sizeof(rxdata);
		mmsg.rx_source_thread = K_ANY;
		zassert_true(k_mbox_get(pmbox, &mmsg, NULL, K_FOREVER) == 0,
			     NULL);
		zassert_equal(mmsg.info, ASYNC_PUT_GET_BUFFER, NULL);
		zassert_equal(mmsg.size, sizeof(data[info_type]), NULL);
		k_mbox_data_get(&mmsg, rxdata);
		zassert_true(memcmp(rxdata, data[info_type], MAIL_LEN) == 0,
			     NULL);
		break;
	case ASYNC_PUT_GET_BLOCK:
	/*fall through*/
	case TARGET_SOURCE_THREAD_BLOCK:
		/**TESTPOINT: mbox async get mem block*/
		mmsg.size = MAIL_LEN;
		if (info_type == TARGET_SOURCE_THREAD_BLOCK) {
			mmsg.rx_source_thread = sender_tid;
		} else {
			mmsg.rx_source_thread = K_ANY;
		}
		zassert_true(k_mbox_get(pmbox, &mmsg, NULL, K_FOREVER) == 0,
			     NULL);
		zassert_true(k_mbox_data_block_get
				     (&mmsg, &mpoolrx, &rxblock, K_FOREVER) == 0, NULL);
		zassert_equal(mmsg.info, ASYNC_PUT_GET_BLOCK, NULL);
		zassert_equal(mmsg.size, MAIL_LEN, NULL);
		/*verify rxblock*/
		zassert_true(memcmp(rxblock.data, data[info_type], MAIL_LEN)
			     == 0, NULL);
		k_mem_pool_free(&rxblock);
		break;
	default:
		break;
	}
}

/*entry of contexts*/
static void tmbox_entry(void *p1, void *p2, void *p3)
{
	tmbox_get((struct k_mbox *)p1);
	k_sem_give(&end_sema);
}

static void tmbox(struct k_mbox *pmbox)
{
	/*test case setup*/
	k_sem_reset(&end_sema);
	k_sem_reset(&sync_sema);

	/**TESTPOINT: thread-thread data passing via mbox*/
	sender_tid = k_current_get();
	receiver_tid = k_thread_create(&tdata, tstack, STACK_SIZE,
				       tmbox_entry, pmbox, NULL, NULL,
				       K_PRIO_PREEMPT(0), 0, 0);
	tmbox_put(pmbox);
	k_sem_take(&end_sema, K_FOREVER);

	/*test case teardown*/
	k_thread_abort(receiver_tid);
}

/*test cases*/
void test_mbox_kinit(void)
{
	/**TESTPOINT: init via k_mbox_init*/
	k_mbox_init(&mbox);
	k_sem_init(&end_sema, 0, 1);
	k_sem_init(&sync_sema, 0, 1);
}

void test_mbox_kdefine(void)
{
	info_type = PUT_GET_NULL;
	tmbox(&kmbox);
}

void test_mbox_put_get_null(void)
{
	info_type = PUT_GET_NULL;
	tmbox(&mbox);
}

void test_mbox_put_get_buffer(void)
{
	info_type = PUT_GET_BUFFER;
	tmbox(&mbox);
}

void test_mbox_async_put_get_buffer(void)
{
	info_type = ASYNC_PUT_GET_BUFFER;
	tmbox(&mbox);
}

void test_mbox_async_put_get_block(void)
{
	info_type = ASYNC_PUT_GET_BLOCK;
	tmbox(&mbox);
}

void test_mbox_target_source_thread_buffer(void)
{
	info_type = TARGET_SOURCE_THREAD_BUFFER;
	tmbox(&mbox);
}

void test_mbox_target_source_thread_block(void)
{
	info_type = TARGET_SOURCE_THREAD_BLOCK;
	tmbox(&mbox);
}
