#include "utilities/RingBuffer.h"
#include "unittest/TestSuite.h"

static void testCreate(void) {
	RingBuffer buffer = RingBuffer_init(4, 8);
	TestCase_assertSizeEqual(buffer.entrySize, 4);
	TestCase_assertUIntEqual(buffer.capacity, 8);
	TestCase_assertUIntEqual(buffer.readIndex, 0);
	TestCase_assertUIntEqual(buffer.writeIndex, 0);
	RingBuffer_free(&buffer);
	
	buffer = RingBuffer_init(16, 2);
	TestCase_assertSizeEqual(buffer.entrySize, 16);
	TestCase_assertUIntEqual(buffer.capacity, 2);
	TestCase_assertUIntEqual(buffer.readIndex, 0);
	TestCase_assertUIntEqual(buffer.writeIndex, 0);
	RingBuffer_free(&buffer);
}

static void testReadWrite(void) {
	RingBuffer buffer = RingBuffer_init(sizeof(unsigned int), 3);
	unsigned int data = 0;
	bool success = RingBuffer_read(&buffer, &data);
	TestCase_assertBoolFalse(success);
	TestCase_assertUIntEqual(buffer.readIndex, 0);
	RingBuffer_write(&buffer, &data);
	TestCase_assertUIntEqual(buffer.writeIndex, 1);
	data = 1;
	RingBuffer_write(&buffer, &data);
	TestCase_assertUIntEqual(buffer.writeIndex, 2);
	
	success = RingBuffer_read(&buffer, &data);
	TestCase_assertBoolTrue(success);
	TestCase_assertUIntEqual(data, 0);
	TestCase_assertUIntEqual(buffer.readIndex, 1);
	success = RingBuffer_read(&buffer, &data);
	TestCase_assertBoolTrue(success);
	TestCase_assertUIntEqual(data, 1);
	TestCase_assertUIntEqual(buffer.readIndex, 2);
	success = RingBuffer_read(&buffer, &data);
	TestCase_assertBoolFalse(success);
	TestCase_assertUIntEqual(buffer.readIndex, 2);
	
	data = 2;
	RingBuffer_write(&buffer, &data);
	TestCase_assertUIntEqual(buffer.writeIndex, 0);
	data = 3;
	RingBuffer_write(&buffer, &data);
	TestCase_assertUIntEqual(buffer.writeIndex, 1);
	success = RingBuffer_read(&buffer, &data);
	TestCase_assertBoolTrue(success);
	TestCase_assertUIntEqual(data, 2);
	TestCase_assertUIntEqual(buffer.readIndex, 0);
	success = RingBuffer_read(&buffer, &data);
	TestCase_assertBoolTrue(success);
	TestCase_assertUIntEqual(data, 3);
	TestCase_assertUIntEqual(buffer.readIndex, 1);
	success = RingBuffer_read(&buffer, &data);
	TestCase_assertBoolFalse(success);
	TestCase_assertUIntEqual(buffer.readIndex, 1);
	RingBuffer_free(&buffer);
}

static void testResize(void) {
	RingBuffer buffer = RingBuffer_init(sizeof(uint16_t), 2);
	uint16_t data = 0;
	RingBuffer_write(&buffer, &data);
	data = 1;
	TestCase_assertUIntEqual(buffer.capacity, 2);
	RingBuffer_write(&buffer, &data);
	TestCase_assertUIntEqual(buffer.capacity, 4);
	TestCase_assertUIntEqual(buffer.writeIndex, 2);
	bool success = RingBuffer_read(&buffer, &data);
	TestCase_assertBoolTrue(success);
	TestCase_assertUIntEqual(data, 0);
	success = RingBuffer_read(&buffer, &data);
	TestCase_assertBoolTrue(success);
	TestCase_assertUIntEqual(data, 1);
	TestCase_assertUIntEqual(buffer.readIndex, 2);
	
	data = 2;
	RingBuffer_write(&buffer, &data);
	data = 3;
	TestCase_assertUIntEqual(buffer.writeIndex, 3);
	RingBuffer_write(&buffer, &data);
	TestCase_assertUIntEqual(buffer.writeIndex, 0);
	data = 4;
	RingBuffer_write(&buffer, &data);
	data = 5;
	TestCase_assertUIntEqual(buffer.capacity, 4);
	RingBuffer_write(&buffer, &data);
	TestCase_assertUIntEqual(buffer.capacity, 8);
	TestCase_assertUIntEqual(buffer.readIndex, 6);
	
	success = RingBuffer_read(&buffer, &data);
	TestCase_assertBoolTrue(success);
	TestCase_assertUIntEqual(data, 2);
	TestCase_assertUIntEqual(buffer.readIndex, 7);
	success = RingBuffer_read(&buffer, &data);
	TestCase_assertBoolTrue(success);
	TestCase_assertUIntEqual(data, 3);
	TestCase_assertUIntEqual(buffer.readIndex, 0);
	success = RingBuffer_read(&buffer, &data);
	TestCase_assertBoolTrue(success);
	TestCase_assertUIntEqual(data, 4);
	TestCase_assertUIntEqual(buffer.readIndex, 1);
	success = RingBuffer_read(&buffer, &data);
	TestCase_assertBoolTrue(success);
	TestCase_assertUIntEqual(data, 5);
	TestCase_assertUIntEqual(buffer.readIndex, 2);
	RingBuffer_free(&buffer);
}

static void testReset(void) {
	RingBuffer buffer = RingBuffer_init(sizeof(uint8_t), 2);
	uint8_t byte = 0;
	RingBuffer_write(&buffer, &byte);
	RingBuffer_write(&buffer, &byte);
	RingBuffer_read(&buffer, &byte);
	RingBuffer_reset(&buffer);
	TestCase_assertUIntEqual(buffer.readIndex, 0);
	TestCase_assertUIntEqual(buffer.writeIndex, 0);
	TestCase_assertUIntEqual(buffer.capacity, 4);
	RingBuffer_free(&buffer);
}

TEST_SUITE(RingBufferTest,
           testCreate,
           testReadWrite,
           testResize,
           testReset)
