/*
 * Copyright (c) 2012-2014 Wind River Systems, Inc.
 *
 * SPDX-License-Identifier: Apache-2.0
 */

/**
 * @file
 * @brief Test microkernel event APIs
 *
 * This modules tests the following event APIs:
 *    task_event_handler_set()
 *    task_event_send()
 *    isr_event_send()
 *    task_event_recv()
 */

#include <tc_util.h>
#include <zephyr.h>
#include <arch/cpu.h>
#include <toolchain.h>
#include <irq_offload.h>

#include <util_test_common.h>

typedef struct {
	kevent_t  event;
} ISR_INFO;

static int  evidence = 0;

static ISR_INFO  isrInfo;
static int  handlerRetVal = 0;

extern void testFiberInit(void);
extern struct nano_sem fiberSem; /* semaphore that allows test control the fiber */

extern kevent_t _k_event_list_end[];

/**
 *
 * @brief ISR handler to signal an event
 *
 * @return N/A
 */

void isr_event_signal_handler(void *data)
{
	ISR_INFO *pInfo = (ISR_INFO *) data;

	isr_event_send(pInfo->event);
}

static void _trigger_isrEventSignal(void)
{
	irq_offload(isr_event_signal_handler, &isrInfo);
}


/**
 *
 * @brief Release the test fiber
 *
 * @return N/A
 */

void releaseTestFiber(void)
{
	nano_task_sem_give(&fiberSem);
}

/**
 *
 * @brief Initialize objects used in this microkernel test suite
 *
 * @return N/A
 */

void microObjectsInit(void)
{
	testFiberInit();

	TC_PRINT("Microkernel objects initialized\n");
}

/**
 *
 * @brief Test the task_event_recv(TICKS_NONE) API
 *
 * There are two cases to be tested here.  The first is for testing for an
 * event when there is one.  The second is for testing for an event when there
 * are none.  Note that the "consumption" of the event gets confirmed by the
 * order in which the latter two checks are done.
 *
 * @return TC_PASS on success, TC_FAIL on failure
 */

int eventNoWaitTest(void)
{
	int  rv;    /* return value from task_event_xxx() calls */

	/* Signal an event */
	rv = task_event_send(EVENT_ID);
	if (rv != RC_OK) {
		TC_ERROR("task_event_send() returned %d, not %d\n", rv, RC_OK);
		return TC_FAIL;
	}

	rv = task_event_recv(EVENT_ID, TICKS_NONE);
	if (rv != RC_OK) {
		TC_ERROR("task_event_recv() returned %d, not %d\n", rv, RC_OK);
		return TC_FAIL;
	}

	/* No event has been signalled */
	rv = task_event_recv(EVENT_ID, TICKS_NONE);
	if (rv != RC_FAIL) {
		TC_ERROR("task_event_recv() returned %d, not %d\n", rv, RC_FAIL);
		return TC_FAIL;
	}

	return TC_PASS;
}

/**
 *
 * @brief Test the task_event_recv(TICKS_UNLIMITED) API
 *
 * This test checks task_event_recv(TICKS_UNLIMITED) against the following
 * cases:
 *  1. There is already an event waiting (signalled from a task and ISR).
 *  2. The current task must wait on the event until it is signalled
 *     from either another task, an ISR or a fiber.
 *
 * @return TC_PASS on success, TC_FAIL on failure
 */

int eventWaitTest(void)
{
	int  rv;     /* return value from task_event_xxx() calls */
	int  i;      /* loop counter */

	/*
	 * task_event_recv() to return immediately as there will already be
	 * an event by a task.
	 */

	task_event_send(EVENT_ID);
	rv = task_event_recv(EVENT_ID, TICKS_UNLIMITED);
	if (rv != RC_OK) {
		TC_ERROR("Task: task_event_recv() returned %d, not %d\n", rv, RC_OK);
		return TC_FAIL;
	}

	/*
	 * task_event_recv() to return immediately as there will already be
	 * an event made ready by an ISR.
	 */

	isrInfo.event = EVENT_ID;
	_trigger_isrEventSignal();
	rv = task_event_recv(EVENT_ID, TICKS_UNLIMITED);
	if (rv != RC_OK) {
		TC_ERROR("ISR: task_event_recv() returned %d, not %d\n", rv, RC_OK);
		return TC_FAIL;
	}

	/*
	 * task_event_recv() to return immediately as there will already be
	 * an event made ready by a fiber.
	 */

	releaseTestFiber();
	rv = task_event_recv(EVENT_ID, TICKS_UNLIMITED);
	if (rv != RC_OK) {
		TC_ERROR("Fiber: task_event_recv() returned %d, not %d\n", rv, RC_OK);
		return TC_FAIL;
	}

	task_sem_give(ALTERNATE_SEM);    /* Wake the AlternateTask */

	/*
	 * The 1st pass, task_event_recv() will be signalled from a task,
	 * from an ISR for the second and from a fiber third.
	 */

	for (i = 0; i < 3; i++) {
		rv = task_event_recv(EVENT_ID, TICKS_UNLIMITED);
		if (rv != RC_OK) {
			TC_ERROR("task_event_recv() returned %d, not %d\n", rv, RC_OK);
			return TC_FAIL;
		}
	}

	return TC_PASS;
}

/**
 *
 * @brief Test the task_event_recv(timeout) API
 *
 * This test checks task_event_recv(timeout) against the following cases:
 *  1. The current task times out while waiting for the event.
 *  2. There is already an event waiting (signalled from a task).
 *  3. The current task must wait on the event until it is signalled
 *     from either another task, an ISR or a fiber.
 *
 * @return TC_PASS on success, TC_FAIL on failure
 */

int eventTimeoutTest(void)
{
	int  rv;     /* return value from task_event_xxx() calls */
	int  i;      /* loop counter */

	/* Timeout while waiting for the event */
	rv = task_event_recv(EVENT_ID, MSEC(100));
	if (rv != RC_TIME) {
		TC_ERROR("task_event_recv() returned %d, not %d\n", rv, RC_TIME);
		return TC_FAIL;
	}

	/* Let there be an event already waiting to be tested */
	task_event_send(EVENT_ID);
	rv = task_event_recv(EVENT_ID, MSEC(100));
	if (rv != RC_OK) {
		TC_ERROR("task_event_recv() returned %d, not %d\n", rv, RC_OK);
		return TC_FAIL;
	}

	task_sem_give(ALTERNATE_SEM);    /* Wake AlternateTask() */

	/*
	 * The 1st pass, task_event_recv(timeout) will be signalled from a task,
	 * from an ISR for the second and from a fiber for the third.
	 */

	for (i = 0; i < 3; i++) {
		rv = task_event_recv(EVENT_ID, MSEC(100));
		if (rv != RC_OK) {
			TC_ERROR("task_event_recv() returned %d, not %d\n", rv, RC_OK);
			return TC_FAIL;
		}
	}

	return TC_PASS;
}

/**
 *
 * @brief Test the isr_event_send() API
 *
 * Although other tests have done some testing using isr_event_send(), none
 * of them have demonstrated that signalling an event more than once does not
 * "queue" events.  That is, should two or more signals of the same event occur
 * before it is tested, it can only be tested for successfully once.
 *
 * @return TC_PASS on success, TC_FAIL on failure
 */

int isrEventSignalTest(void)
{
	int  rv;    /* return value from task_event_recv() */

	/*
	 * The single case of an event made ready has already been tested.
	 * Trigger two ISR event signals.  Only one should be detected.
	 */

	isrInfo.event = EVENT_ID;

	_trigger_isrEventSignal();
	_trigger_isrEventSignal();

	rv = task_event_recv(EVENT_ID, TICKS_NONE);
	if (rv != RC_OK) {
		TC_ERROR("task_event_recv() returned %d, not %d\n", rv, RC_OK);
		return TC_FAIL;
	}

	/* The second event signal should be "lost" */
	rv = task_event_recv(EVENT_ID, TICKS_NONE);
	if (rv != RC_FAIL) {
		TC_ERROR("task_event_recv() returned %d, not %d\n", rv, RC_FAIL);
		return TC_FAIL;
	}

	return TC_PASS;
}

/**
 *
 * @brief Test the fiber_event_send() API
 *
 * Signalling an event by fiber_event_send() more than once does not "queue"
 * events.  That is, should two or more signals of the same event occur before
 * it is tested, it can only be tested for successfully once.
 *
 * @return TC_PASS on success, TC_FAIL on failure
 */

int fiberEventSignalTest(void)
{
	int  rv;    /* return value from task_event_recv(TICKS_NONE) */

	/*
	 * Trigger two fiber event signals.  Only one should be detected.
	 */

	releaseTestFiber();

	rv = task_event_recv(EVENT_ID, TICKS_NONE);
	if (rv != RC_OK) {
		TC_ERROR("task_event_recv() returned %d, not %d\n", rv, RC_OK);
		return TC_FAIL;
	}

	/* The second event signal should be "lost" */
	rv = task_event_recv(EVENT_ID, TICKS_NONE);
	if (rv != RC_FAIL) {
		TC_ERROR("task_event_recv() returned %d, not %d\n", rv, RC_FAIL);
		return TC_FAIL;
	}

	return TC_PASS;
}

/**
 *
 * @brief Handler to run on EVENT_ID event
 *
 * @param event    signalled event
 *
 * @return <handlerRetVal>
 */

int eventHandler(int event)
{
	ARG_UNUSED(event);

	evidence++;

	return handlerRetVal;    /* 0 if not to wake waiting task; 1 if to wake */
}

/**
 *
 * @brief Handler to run on ALT_EVENT event
 *
 * @param event    signalled event
 *
 * @return 1
 */

int altEventHandler(int event)
{
	ARG_UNUSED(event);

	evidence += 100;

	return 1;
}

/**
 *
 * @brief Test the task_event_handler_set() API
 *
 * This test checks that the event handler is set up properly when
 * task_event_handler_set() is called.  It shows that event handlers are tied
 * to the specified event and that the return value from the handler affects
 * whether the event wakes a task waiting upon that event.
 *
 * @return TC_PASS on success, TC_FAIL on failure
 */

int eventSignalHandlerTest(void)
{
	int  rv;     /* return value from task_event_xxx() calls */

	/*
	 * NOTE: We cannot test for the validity of an event ID, since
	 * task_event_handler_set() only checks for valid event IDs via an
	 * __ASSERT() and only in debug kernels (an __ASSERT() stops the system).
	 */

	/* Expect this call to task_event_handler_set() to succeed */
	rv = task_event_handler_set(EVENT_ID, eventHandler);
	if (rv != RC_OK) {
		TC_ERROR("task_event_handler_set() returned %d not %d\n",
			rv, RC_OK);
		return TC_FAIL;
	}

	/* Enable another handler to show that two handlers can be installed */
	rv = task_event_handler_set(ALT_EVENT, altEventHandler);
	if (rv != RC_OK) {
		TC_ERROR("task_event_handler_set() returned %d not %d\n",
			rv, RC_OK);
		return TC_FAIL;
	}

	/*
	 * The alternate task should signal the event, but the handler will
	 * return 0 and the waiting task will not be woken up.  Thus, it should
	 * timeout and get an RC_TIME return code.
	 */

	task_sem_give(ALTERNATE_SEM);    /* Wake alternate task */
	rv = task_event_recv(EVENT_ID, MSEC(100));
	if (rv != RC_TIME) {
		TC_ERROR("task_event_recv() returned %d not %d\n", rv, RC_TIME);
		return TC_FAIL;
	}

	/*
	 * The alternate task should signal the event, and the handler will
	 * return 1 this time, which will wake the waiting task.
	 */

	task_sem_give(ALTERNATE_SEM);    /* Wake alternate task again */
	rv = task_event_recv(EVENT_ID, MSEC(100));
	if (rv != RC_OK) {
		TC_ERROR("task_event_recv() returned %d not %d\n", rv, RC_OK);
		return TC_FAIL;
	}

	if (evidence != 2) {
		TC_ERROR("Expected event handler evidence to be %d not %d\n",
			2, evidence);
		return TC_FAIL;
	}

	/*
	 * Signal the alternate event.  This demonstrates that two event handlers
	 * can be simultaneously installed for two different events.
	 */

	task_event_send(ALT_EVENT);
	if (evidence != 102) {
		TC_ERROR("Expected event handler evidence to be %d not %d\n",
			2, evidence);
		return TC_FAIL;
	}

	/* Uninstall the event handlers */
	rv = task_event_handler_set(EVENT_ID, NULL);
	if (rv != RC_OK) {
		TC_ERROR("task_event_handler_set() returned %d not %d\n",
			rv, RC_OK);
		return TC_FAIL;
	}

	rv = task_event_handler_set(ALT_EVENT, NULL);
	if (rv != RC_OK) {
		TC_ERROR("task_event_handler_set() returned %d not %d\n",
			rv, RC_OK);
		return TC_FAIL;
	}

	task_event_send(EVENT_ID);
	task_event_send(ALT_EVENT);

	if (evidence != 102) {
		TC_ERROR("Event handlers did not uninstall\n");
		return TC_FAIL;
	}

	/* Clear out the waiting events */

	rv = task_event_recv(EVENT_ID, TICKS_NONE);
	if (rv != RC_OK) {
		TC_ERROR("task_event_recv() returned %d not %d\n", rv, RC_OK);
		return TC_FAIL;
	}

	rv = task_event_recv(ALT_EVENT, TICKS_NONE);
	if (rv != RC_OK) {
		TC_ERROR("task_event_recv() returned %d not %d\n", rv, RC_OK);
		return TC_FAIL;
	}

	return TC_PASS;
}

/**
 *
 * @brief Alternate task to signal various events to a waiting task
 *
 * @return N/A
 */

void AlternateTask(void)
{
	/* Wait for eventWaitTest() to run. */
	task_sem_take(ALTERNATE_SEM, TICKS_UNLIMITED);
	task_event_send(EVENT_ID);
	releaseTestFiber();
	_trigger_isrEventSignal();

	/* Wait for eventTimeoutTest() to run. */
	task_sem_take(ALTERNATE_SEM, TICKS_UNLIMITED);
	task_event_send(EVENT_ID);
	releaseTestFiber();
	_trigger_isrEventSignal();

	/*
	 * Wait for eventSignalHandlerTest() to run.
	 *
	 * When <handlerRetVal> is zero (0), the waiting task will not get woken up
	 * after the event handler for EVENT_ID runs.  When it is one (1), the
	 * waiting task will get woken up after the event handler for EVENT_ID runs.
	 */

	task_sem_take(ALTERNATE_SEM, TICKS_UNLIMITED);
	handlerRetVal = 0;
	task_event_send(EVENT_ID);

	task_sem_take(ALTERNATE_SEM, TICKS_UNLIMITED);
	handlerRetVal = 1;
	task_event_send(EVENT_ID);
}

/**
 *
 * @brief Main entry point to the test suite
 *
 * @return N/A
 */

void RegressionTask(void)
{
	int  tcRC;    /* test case return code */

	TC_START("Test Microkernel Events\n");

	microObjectsInit();

	TC_PRINT("Testing task_event_recv(TICKS_NONE) and task_event_send() ...\n");
	tcRC = eventNoWaitTest();
	if (tcRC != TC_PASS) {
		goto doneTests;
	}

	TC_PRINT("Testing task_event_recv(TICKS_UNLIMITED) and task_event_send() ...\n");
	tcRC = eventWaitTest();
	if (tcRC != TC_PASS) {
		goto doneTests;
	}

	TC_PRINT("Testing task_event_recv(timeout) and task_event_send() ...\n");
	tcRC = eventTimeoutTest();
	if (tcRC != TC_PASS) {
		goto doneTests;
	}

	TC_PRINT("Testing isr_event_send() ...\n");
	tcRC = isrEventSignalTest();
	if (tcRC != TC_PASS) {
		goto doneTests;
	}

	TC_PRINT("Testing fiber_event_send() ...\n");
	tcRC = fiberEventSignalTest();
	if (tcRC != TC_PASS) {
		goto doneTests;
	}

	TC_PRINT("Testing task_event_handler_set() ...\n");
	tcRC = eventSignalHandlerTest();
	if (tcRC != TC_PASS) {
		goto doneTests;
	}

doneTests:
	TC_END_RESULT(tcRC);
	TC_END_REPORT(tcRC);
}
