/*
 * Copyright (c) 2021 Intel Corporation
 *
 * SPDX-License-Identifier: Apache-2.0
 */
#include <zephyr/ztest.h>
#include <zephyr/ztress.h>
#include <zephyr/sys/ring_buffer.h>
#include <zephyr/sys/mutex.h>
#include <zephyr/random/random.h>
#include <stdint.h>

/**
 * @defgroup lib_ringbuffer_tests Ringbuffer
 * @ingroup all_tests
 * @{
 * @}
 */

#define STACKSIZE (512 + CONFIG_TEST_EXTRA_STACK_SIZE)

#define RINGBUFFER			256
#define LENGTH				64
#define VALUE				0xb
#define TYPE				0xc

static ZTEST_BMEM SYS_MUTEX_DEFINE(mutex);
RING_BUF_ITEM_DECLARE(ringbuf, RINGBUFFER);
static uint32_t data_output[LENGTH];
static uint32_t databuffer1[LENGTH];
static uint32_t databuffer2[LENGTH];

static void data_write(uint32_t *input)
{
	sys_mutex_lock(&mutex, K_FOREVER);
	int ret = ring_buf_item_put(&ringbuf, TYPE, VALUE,
				   input, LENGTH);
	zassert_equal(ret, 0);
	sys_mutex_unlock(&mutex);
}

static void data_read(uint32_t *output)
{
	uint16_t type;
	uint8_t value, size32 = LENGTH;
	int ret;

	sys_mutex_lock(&mutex, K_FOREVER);
	ret = ring_buf_item_get(&ringbuf, &type, &value, output, &size32);
	sys_mutex_unlock(&mutex);

	zassert_equal(ret, 0);
	zassert_equal(type, TYPE);
	zassert_equal(value, VALUE);
	zassert_equal(size32, LENGTH);
	if (output[0] == 1) {
		zassert_equal(memcmp(output, databuffer1, size32), 0);
	} else {
		zassert_equal(memcmp(output, databuffer2, size32), 0);
	}
}

static bool user_handler(void *user_data, uint32_t iter_cnt, bool last, int prio)
{
	uintptr_t id = (uintptr_t)user_data;
	uint32_t *buffer = id ? databuffer2 : databuffer1;

	if (iter_cnt == 0) {
		for (int i = 0; i < LENGTH; i++) {
			buffer[i] = 1;
		}
	}

	/* Try to write data into the ringbuffer */
	data_write(buffer);
	/* Try to get data from the ringbuffer and check */
	data_read(data_output);

	return true;
}

/**
 * @brief Test that prevent concurrent writing
 * operations by using a mutex
 *
 * @details Define a ring buffer and a mutex,
 * and then spawn two threads to read and
 * write the same buffer at the same time to
 * check the integrity of data reading and writing.
 *
 * @ingroup lib_ringbuffer_tests
 */
ZTEST(ringbuffer_api, test_ringbuffer_concurrent)
{
	ztress_set_timeout(K_MSEC(1000));
	ZTRESS_EXECUTE(ZTRESS_THREAD(user_handler, (void *)0, 0, 0, Z_TIMEOUT_TICKS(20)),
		       ZTRESS_THREAD(user_handler, (void *)1, 0, 10, Z_TIMEOUT_TICKS(20)));
}

static bool produce_cpy(void *user_data, uint32_t iter_cnt, bool last, int prio)
{
	static int cnt;
	uint8_t buf[3];
	uint32_t len;

	if (iter_cnt == 0) {
		cnt = 0;
	}

	for (int i = 0; i < sizeof(buf); i++) {
		buf[i] = (uint8_t)cnt++;
	}

	len = ring_buf_put(&ringbuf, buf, sizeof(buf));
	cnt -= (sizeof(buf) - len);

	return true;
}

static bool consume_cpy(void *user_data, uint32_t iter_cnt, bool last, int prio)
{
	static int cnt;
	uint8_t buf[3];
	uint32_t len;

	if (iter_cnt == 0) {
		cnt = 0;
	}

	len = ring_buf_get(&ringbuf, buf, sizeof(buf));
	for (int i = 0; i < len; i++) {
		zassert_equal(buf[i], (uint8_t)cnt);
		cnt++;
	}

	return true;
}

static bool produce_item(void *user_data, uint32_t cnt, bool last, int prio)
{
	int err;
	static uint32_t pcnt;
	uint32_t buf[2];

	if (cnt == 0) {
		pcnt = 0;
	}

	err = ring_buf_item_put(&ringbuf, (uint16_t)pcnt, VALUE, buf, 2);
	if (err == 0) {
		pcnt++;
	}

	return true;
}

static bool consume_item(void *user_data, uint32_t cnt, bool last, int prio)
{
	int err;
	static uint32_t pcnt;
	uint32_t data[2];
	uint16_t type;
	uint8_t value;
	uint8_t size32 = ARRAY_SIZE(data);

	if (cnt == 0) {
		pcnt = 0;
	}

	err = ring_buf_item_get(&ringbuf, &type, &value, data, &size32);
	if (err == 0) {
		zassert_equal(value, VALUE);
		zassert_equal(type, (uint16_t)pcnt);
		pcnt++;
	} else if (err == -EMSGSIZE) {
		zassert_true(false);
	}

	return true;
}

static bool produce(void *user_data, uint32_t iter_cnt, bool last, int prio)
{
	static int cnt;
	static int wr = 8;
	uint32_t len;
	uint8_t *data;

	if (iter_cnt == 0) {
		cnt = 0;
	}

	len = ring_buf_put_claim(&ringbuf, &data, wr);
	if (len == 0) {
		len = ring_buf_put_claim(&ringbuf, &data, wr);
	}

	if (len == 0) {
		return true;
	}

	for (uint32_t i = 0; i < len; i++) {
		data[i] = cnt++;
	}

	wr++;
	if (wr == 15) {
		wr = 8;
	}

	int err = ring_buf_put_finish(&ringbuf, len);

	zassert_equal(err, 0, "cnt: %d", cnt);

	return true;
}

static bool consume(void *user_data, uint32_t iter_cnt, bool last, int prio)
{
	static int rd = 8;
	static int cnt;
	uint32_t len;
	uint8_t *data;

	if (iter_cnt == 0) {
		cnt = 0;
	}

	len = ring_buf_get_claim(&ringbuf, &data, rd);
	if (len == 0) {
		len = ring_buf_get_claim(&ringbuf, &data, rd);
	}

	if (len == 0) {
		return true;
	}

	for (uint32_t i = 0; i < len; i++) {
		zassert_equal(data[i], (uint8_t)cnt,
			      "Got %02x, exp: %02x", data[i], (uint8_t)cnt);
		cnt++;
	}

	rd++;
	if (rd == 15) {
		rd = 8;
	}

	int err = ring_buf_get_finish(&ringbuf, len);

	zassert_equal(err, 0);

	return true;
}

static void test_ztress(ztress_handler high_handler,
			ztress_handler low_handler,
			bool item_mode)
{
	union {
		uint8_t buf8[32];
		uint32_t buf32[32];
	} buf;
	k_timeout_t timeout;
	int32_t offset;

	if (item_mode) {
		ring_buf_item_init(&ringbuf, ARRAY_SIZE(buf.buf32), buf.buf32);
	} else {
		ring_buf_init(&ringbuf, ARRAY_SIZE(buf.buf8), buf.buf8);
	}

	/* force internal 32-bit index roll-over */
	offset = INT32_MAX - ring_buf_capacity_get(&ringbuf)/2;
	ring_buf_internal_reset(&ringbuf, offset);

	/* Timeout after 5 seconds. */
	timeout =  (CONFIG_SYS_CLOCK_TICKS_PER_SEC < 10000) ? K_MSEC(1000) : K_MSEC(10000);

	ztress_set_timeout(timeout);
	ZTRESS_EXECUTE(ZTRESS_THREAD(high_handler, NULL, 0, 0, Z_TIMEOUT_TICKS(20)),
		       ZTRESS_THREAD(low_handler, NULL, 0, 2000, Z_TIMEOUT_TICKS(20)));
}

void test_ringbuffer_stress(ztress_handler produce_handler,
			    ztress_handler consume_handler,
			    bool item_mode)
{
	PRINT("Producing interrupts consuming\n");
	test_ztress(produce_handler, consume_handler, item_mode);

	PRINT("Consuming interrupts producing\n");
	test_ztress(consume_handler, produce_handler, item_mode);
}

/* Zero-copy API. Test is validating single producer, single consumer from
 * different priorities.
 */
ZTEST(ringbuffer_api, test_ringbuffer_zerocpy_stress)
{
	test_ringbuffer_stress(produce, consume, false);
}

/* Copy API. Test is validating single producer, single consumer from
 * different priorities.
 */
ZTEST(ringbuffer_api, test_ringbuffer_cpy_stress)
{
	test_ringbuffer_stress(produce_cpy, consume_cpy, false);
}

/* Item API. Test is validating single producer, single consumer from
 * different priorities.
 */
ZTEST(ringbuffer_api, test_ringbuffer_item_stress)
{
	test_ringbuffer_stress(produce_item, consume_item, true);
}
