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

#include <ztest.h>
#include <zephyr/kernel.h>
#include <cmsis_os.h>

struct sample_data {
	int		data1;
	unsigned char	data2;
	unsigned int	data3;
};

#define MAIL1_DATA1	75663
#define MAIL1_DATA2	156
#define MAIL1_DATA3	1000001

#define MAIL2_DATA1	93567
#define MAIL2_DATA2	255
#define MAIL2_DATA3	1234567

#define TIMEOUT		500
#define Q_LEN		5

osMailQDef(mail, Q_LEN, struct sample_data);
osMailQId  mail_id;

void send_thread(void const *argument)
{
	int i;
	struct sample_data *tx_ptr;
	struct sample_data zeroblock;
	osStatus status;

	/* This is used for comparison later in the function */
	memset(&zeroblock, 0, sizeof(struct sample_data));

	status = osMailPut(mail_id, NULL);
	zassert_true(status == osErrorValue,
	 "Something's wrong with osMailPut. It is passing for NULL mail!");

	/* Wait for mail_recv to complete initial checks */
	osDelay(TIMEOUT);

	/* Prepare and send 1st mail */
	tx_ptr = osMailAlloc(mail_id, osWaitForever);
	zassert_true(tx_ptr != NULL, "Mail1 alloc failed");
	tx_ptr->data1 = MAIL1_DATA1;
	tx_ptr->data2 = MAIL1_DATA2;
	tx_ptr->data3 = MAIL1_DATA3;
	status = osMailPut(mail_id, tx_ptr);
	zassert_true(status == osOK, "osMailPut failure for mail1");

	/* Fill the queue with blocks of mails */
	for (i = 0; i < Q_LEN; i++) {

		/* Alternately use osMailAlloc and osMailCAlloc to ensure
		 * both the APIs are tested.
		 */
		if (i & 1) {
			tx_ptr = osMailCAlloc(mail_id, osWaitForever);
		} else {
			tx_ptr = osMailAlloc(mail_id, osWaitForever);
		}
		zassert_true(tx_ptr != NULL, "Mail alloc failed");

		tx_ptr->data1 = i;
		tx_ptr->data2 = i+1;
		tx_ptr->data3 = i+2;

		status = osMailPut(mail_id, tx_ptr);
		zassert_true(status == osOK,
				"osMailPut failure for mail!");
	}

	/* Try allocating mail to a full queue immediately
	 * before it is emptied out and assert failure
	 */
	tx_ptr = osMailAlloc(mail_id, 0);
	zassert_true(tx_ptr == NULL, "MailAlloc passed. Something's wrong");
	tx_ptr = osMailCAlloc(mail_id, 0);
	zassert_true(tx_ptr == NULL, "MailCAlloc passed. Something's wrong");

	/* Try allocating mail to a full queue within a duration
	 * less than TIMEOUT, before the queue is emptied out
	 */
	tx_ptr = osMailAlloc(mail_id, TIMEOUT/3);
	zassert_true(tx_ptr == NULL, "MailAlloc passed. Something's wrong");
	tx_ptr = osMailCAlloc(mail_id, TIMEOUT/3);
	zassert_true(tx_ptr == NULL, "MailCAlloc passed. Something's wrong");

	/* Send another mail after the queue is emptied */
	tx_ptr = osMailCAlloc(mail_id, TIMEOUT*2);
	zassert_true(tx_ptr != NULL, "Mail alloc failed");
	zassert_equal(memcmp(tx_ptr, &zeroblock, sizeof(struct sample_data)), 0,
		"osMailCAlloc returned memory not initialized to 0");

	tx_ptr->data1 = MAIL2_DATA1;
	tx_ptr->data2 = MAIL2_DATA2;
	tx_ptr->data3 = MAIL2_DATA3;
	status = osMailPut(mail_id, tx_ptr);
	zassert_true(status == osOK, "osMailPut failure for mail");
}

void mail_recv(void)
{
	int i;
	struct sample_data  *rx_ptr;
	osEvent  evt;
	osStatus status;

	/* Try getting mail immediately before the queue is populated */
	evt = osMailGet(mail_id, 0);
	zassert_true(evt.status == osOK,
			"Something's wrong with osMailGet!");

	/* Try receiving mail within a duration of TIMEOUT */
	evt = osMailGet(mail_id, TIMEOUT);
	zassert_true(evt.status == osEventTimeout,
		"Something's wrong with osMailGet!");

	/* Receive 1st mail */
	evt = osMailGet(mail_id, osWaitForever);
	zassert_true(evt.status == osEventMail, "osMailGet failure");

	rx_ptr = evt.value.p;
	zassert_equal(rx_ptr->data1, MAIL1_DATA1, NULL);
	zassert_equal(rx_ptr->data2, MAIL1_DATA2, NULL);
	zassert_equal(rx_ptr->data3, MAIL1_DATA3, NULL);

	status = osMailFree(mail_id, rx_ptr);
	zassert_true(status == osOK, "osMailFree failure");

	/* Wait for queue to get filled */
	osDelay(TIMEOUT);

	/* Empty the queue */
	for (i = 0; i < Q_LEN; i++) {
		evt = osMailGet(mail_id, osWaitForever);
		zassert_true(evt.status == osEventMail, "osMailGet failure");

		rx_ptr = evt.value.p;
		zassert_equal(rx_ptr->data1, i, NULL);
		zassert_equal(rx_ptr->data2, i + 1, NULL);
		zassert_equal(rx_ptr->data3, i + 2, NULL);

		status = osMailFree(mail_id, rx_ptr);
		zassert_true(status == osOK, "osMailFree failure");
	}

	/* Receive the next mail */
	evt = osMailGet(mail_id, osWaitForever);
	zassert_true(evt.status == osEventMail, "osMailGet failure");

	rx_ptr = evt.value.p;
	zassert_equal(rx_ptr->data1, MAIL2_DATA1, NULL);
	zassert_equal(rx_ptr->data2, MAIL2_DATA2, NULL);
	zassert_equal(rx_ptr->data3, MAIL2_DATA3, NULL);

	status = osMailFree(mail_id, rx_ptr);
	zassert_true(status == osOK, "osMailFree failure");
}

osThreadDef(send_thread, osPriorityNormal, 1, 0);

void test_mailq(void)
{
	osThreadId tid;

	mail_id = osMailCreate(osMailQ(mail), NULL);
	zassert_true(mail_id != NULL, "Mail creation failed");

	tid = osThreadCreate(osThread(send_thread), NULL);
	zassert_true(tid != NULL, "Thread creation failed");

	mail_recv();
}
