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

/**
 * @brief Test memory slab APIs
 *
 * @defgroup kernel_memory_slab_tests Memory Slab Tests
 *
 * @ingroup all_tests
 *
 * This module tests the following memory slab routines:
 *
 *     k_mem_slab_alloc
 *     k_mem_slab_free
 *     k_mem_slab_num_used_get
 *
 * @note
 * One should ensure that the block is released to the same memory slab from
 * which it was allocated, and is only released once.  Using an invalid pointer
 * will have unpredictable side effects.
 */

#include <tc_util.h>
#include <stdbool.h>
#include <zephyr.h>
#include <ztest.h>

/* size of stack area used by each thread */
#define STACKSIZE (1024 + CONFIG_TEST_EXTRA_STACK_SIZE)

/* Number of memory blocks. The minimum number of blocks needed to run the
 * test is 2
 */
#define NUMBLOCKS   4

void test_slab_get_all_blocks(void **p);
void test_slab_free_all_blocks(void **p);


K_SEM_DEFINE(SEM_HELPERDONE, 0, 1);
K_SEM_DEFINE(SEM_REGRESSDONE, 0, 1);

K_MEM_SLAB_DEFINE(map_lgblks, 1024, NUMBLOCKS, 4);


/**
 *
 * @brief Helper task
 *
 * This routine gets all blocks from the memory slab.  It uses semaphores
 * SEM_REGRESDONE and SEM_HELPERDONE to synchronize between different parts
 * of the test.
 *
 */

void helper_thread(void)
{
	void *ptr[NUMBLOCKS];           /* Pointer to memory block */

	(void)memset(ptr, 0, sizeof(ptr));    /* keep static checkers happy */
	/* Wait for part 1 to complete */
	k_sem_take(&SEM_REGRESSDONE, K_FOREVER);

	/* Part 2 of test */

	TC_PRINT("(2) - Allocate %d blocks in <%s>\n", NUMBLOCKS, __func__);

	/* Test k_mem_slab_alloc */
	test_slab_get_all_blocks(ptr);

	k_sem_give(&SEM_HELPERDONE);  /* Indicate part 2 is complete */
	/* Wait for part 3 to complete */
	k_sem_take(&SEM_REGRESSDONE, K_FOREVER);

	/*
	 * Part 4 of test.
	 * Free the first memory block.  RegressionTask is currently blocked
	 * waiting (with a timeout) for a memory block.  Freeing the memory
	 * block will unblock RegressionTask.
	 */
	TC_PRINT("(4) - Free a block in <%s> to unblock the other task "
		 "from alloc timeout\n", __func__);

	TC_PRINT("%s: About to free a memory block\n", __func__);
	k_mem_slab_free(&map_lgblks, &ptr[0]);
	k_sem_give(&SEM_HELPERDONE);

	/* Part 5 of test */
	k_sem_take(&SEM_REGRESSDONE, K_FOREVER);
	TC_PRINT("(5) <%s> freeing the next block\n", __func__);
	TC_PRINT("%s: About to free another memory block\n", __func__);
	k_mem_slab_free(&map_lgblks, &ptr[1]);

	/*
	 * Free all the other blocks.  The first 2 blocks are freed by this task
	 */
	for (int i = 2; i < NUMBLOCKS; i++) {
		k_mem_slab_free(&map_lgblks, &ptr[i]);
	}
	TC_PRINT("%s: freed all blocks allocated by this task\n", __func__);


	k_sem_give(&SEM_HELPERDONE);

}  /* helper thread */


/**
 *
 * @brief Get all blocks from the memory slab
 *
 * Get all blocks from the memory slab.  It also tries to get one more block
 * from the map after the map is empty to verify the error return code.
 *
 * This routine tests the following:
 *
 *   k_mem_slab_alloc(), k_mem_slab_num_used_get()
 *
 * @param p    pointer to pointer of allocated blocks
 *
 */

void test_slab_get_all_blocks(void **p)
{
	void *errptr;   /* Pointer to block */

	for (int i = 0; i < NUMBLOCKS; i++) {
		/* Verify number of used blocks in the map */
		zassert_equal(k_mem_slab_num_used_get(&map_lgblks), i,
			      "Failed k_mem_slab_num_used_get");

		/* Get memory block */
		zassert_equal(k_mem_slab_alloc(&map_lgblks, &p[i], K_NO_WAIT), 0,
			      "Failed k_mem_slab_alloc");
	} /* for */

	/*
	 * Verify number of used blocks in the map - expect all blocks are
	 * used
	 */
	zassert_equal(k_mem_slab_num_used_get(&map_lgblks), NUMBLOCKS,
		      "Failed k_mem_slab_num_used_get");

	/* Try to get one more block and it should fail */
	zassert_equal(k_mem_slab_alloc(&map_lgblks, &errptr, K_NO_WAIT), -ENOMEM,
		      "Failed k_mem_slab_alloc");

}  /* test_slab_get_all_blocks */

/**
 *
 * @brief Free all memory blocks
 *
 * This routine frees all memory blocks and also verifies that the number of
 * blocks used are correct.
 *
 * This routine tests the following:
 *
 *   k_mem_slab_free(&), k_mem_slab_num_used_get(&)
 *
 * @param p    pointer to pointer of allocated blocks
 *
 */

void test_slab_free_all_blocks(void **p)
{
	for (int i = 0; i < NUMBLOCKS; i++) {
		/* Verify number of used blocks in the map */
		zassert_equal(k_mem_slab_num_used_get(&map_lgblks), NUMBLOCKS - i,
			      "Failed k_mem_slab_num_used_get");

		TC_PRINT("  block ptr to free p[%d] = %p\n", i, p[i]);
		/* Free memory block */
		k_mem_slab_free(&map_lgblks, &p[i]);

		TC_PRINT("map_lgblks freed %d block\n", i + 1);

	} /* for */

	/*
	 * Verify number of used blocks in the map
	 *  - should be 0 as no blocks are used
	 */

	zassert_equal(k_mem_slab_num_used_get(&map_lgblks), 0,
		      "Failed k_mem_slab_num_used_get");

}   /* test_slab_free_all_blocks */

/**
 *
 * @brief Main task to test memory slab interfaces
 *
 * @ingroup kernel_memory_slab_tests
 *
 * @details Verify that system allows for the definitions of boot-time
 * memory regions.
 * This routine calls test_slab_get_all_blocks() to get all
 * memory blocks from the map and calls test_slab_free_all_blocks()
 * to free all memory blocks. It also tries to wait (with and without
 * timeout) for a memory block.
 *
 * @see k_mem_slab_alloc(), k_mem_slab_num_used_get(),
 * memset(), k_mem_slab_free()
 */

void test_mslab(void)
{
	int ret_value;                  /* task_mem_map_xxx interface return value */
	void *b;                        /* Pointer to memory block */
	void *ptr[NUMBLOCKS];           /* Pointer to memory block */

	/* not strictly necessary, but keeps coverity checks happy */
	(void)memset(ptr, 0, sizeof(ptr));

	/* Part 1 of test */

	TC_PRINT("(1) - Allocate and free %d blocks "
		 "in <%s>\n", NUMBLOCKS, __func__);

	/* Test k_mem_slab_alloc */
	test_slab_get_all_blocks(ptr);

	/* Test task_mem_map_free */
	test_slab_free_all_blocks(ptr);

	k_sem_give(&SEM_REGRESSDONE);   /* Allow helper thread to run */
	/* Wait for helper thread to finish */
	k_sem_take(&SEM_HELPERDONE, K_FOREVER);

	/*
	 * Part 3 of test.
	 *
	 * helper thread got all memory blocks.  There is no free block left.
	 * The call will timeout.  Note that control does not switch back to
	 * helper thread as it is waiting for SEM_REGRESSDONE.
	 */

	TC_PRINT("(3) - Further allocation results in  timeout "
		 "in <%s>\n", __func__);

	ret_value = k_mem_slab_alloc(&map_lgblks, &b, K_MSEC(20));
	zassert_equal(-EAGAIN, ret_value,
		      "Failed k_mem_slab_alloc, retValue %d\n", ret_value);

	TC_PRINT("%s: start to wait for block\n", __func__);
	k_sem_give(&SEM_REGRESSDONE);    /* Allow helper thread to run part 4 */
	ret_value = k_mem_slab_alloc(&map_lgblks, &b, K_MSEC(50));
	zassert_equal(0, ret_value,
		      "Failed k_mem_slab_alloc, ret_value %d\n", ret_value);

	/* Wait for helper thread to complete */
	k_sem_take(&SEM_HELPERDONE, K_FOREVER);

	TC_PRINT("%s: start to wait for block\n", __func__);
	k_sem_give(&SEM_REGRESSDONE);    /* Allow helper thread to run part 5 */
	ret_value = k_mem_slab_alloc(&map_lgblks, &b, K_FOREVER);
	zassert_equal(0, ret_value,
		      "Failed k_mem_slab_alloc, ret_value %d\n", ret_value);

	/* Wait for helper thread to complete */
	k_sem_take(&SEM_HELPERDONE, K_FOREVER);


	/* Free memory block */
	TC_PRINT("%s: Used %d block\n", __func__,
		 k_mem_slab_num_used_get(&map_lgblks));
	k_mem_slab_free(&map_lgblks, &b);
	TC_PRINT("%s: 1 block freed, used %d block\n",
		 __func__,  k_mem_slab_num_used_get(&map_lgblks));
}

K_THREAD_DEFINE(HELPER, STACKSIZE, helper_thread, NULL, NULL, NULL,
		7, 0, 0);

/*test case main entry*/
void test_main(void)
{
	ztest_test_suite(memory_slab,
			 ztest_1cpu_unit_test(test_mslab));
	ztest_run_test_suite(memory_slab);
}
