#include "gamemath/Grid.h"
#include "unittest/TestSuite.h"
#include <limits.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>

static void printBytes(const uint8_t * bytes, unsigned int width, unsigned int height) {
	for (unsigned int rowIndex = 0; rowIndex < height; rowIndex++) {
		fprintf(stderr, "  ");
		for (unsigned int columnIndex = 0; columnIndex < width; columnIndex++) {
			fprintf(stderr, "%02X ", bytes[rowIndex * width + columnIndex]);
		}
		fputc('\n', stderr);
	}
}

static void assertBytesEqual(uint8_t * bytes, const uint8_t * expectedBytes, unsigned int width, unsigned int height, unsigned int line) {
	for (unsigned int rowIndex = 0; rowIndex < height; rowIndex++) {
		for (unsigned int columnIndex = 0; columnIndex < width; columnIndex++) {
			if (bytes[rowIndex * width + columnIndex] != expectedBytes[rowIndex * width + columnIndex]) {
				fprintf(stderr, "Expected bytes:\n");
				printBytes(expectedBytes, width, height);
				fprintf(stderr, "Actual bytes:\n");
				printBytes(bytes, width, height);
				TestCase_assert(false, "Byte data mismatch at %u, %u (line %u)", columnIndex, rowIndex, line);
				return;
			}
		}
	}
	TestCase_assert(true, NULL);
}

static void testClampGridCopyRegion(void) {
	unsigned int startX = UINT_MAX, startY = UINT_MAX;
	unsigned int copyWidth = 1, copyHeight = 1;
	clampGridCopyRegion(0, 0, 0, 0, 1, 1, 1, 1, &copyWidth, &copyHeight, &startX, &startY);
	TestCase_assertUIntEqual(startX, 0);
	TestCase_assertUIntEqual(startY, 0);
	TestCase_assertUIntEqual(copyWidth, 1);
	TestCase_assertUIntEqual(copyHeight, 1);
	
	copyWidth = 2;
	copyHeight = 3;
	clampGridCopyRegion(0, 0, 0, 0, 1, 1, 1, 1, &copyWidth, &copyHeight, &startX, &startY);
	TestCase_assertUIntEqual(startX, 0);
	TestCase_assertUIntEqual(startY, 0);
	TestCase_assertUIntEqual(copyWidth, 1);
	TestCase_assertUIntEqual(copyHeight, 1);
	
	copyWidth = 8;
	copyHeight = 6;
	clampGridCopyRegion(-1, -2, 1, 1, 8, 6, 4, 3, &copyWidth, &copyHeight, &startX, &startY);
	TestCase_assertUIntEqual(startX, 1);
	TestCase_assertUIntEqual(startY, 2);
	TestCase_assertUIntEqual(copyWidth, 3);
	TestCase_assertUIntEqual(copyHeight, 2);
	
	copyWidth = 5;
	copyHeight = 5;
	clampGridCopyRegion(0, 0, -2, -3, 5, 5, 10, 10, &copyWidth, &copyHeight, &startX, &startY);
	TestCase_assertUIntEqual(startX, 2);
	TestCase_assertUIntEqual(startY, 3);
	TestCase_assertUIntEqual(copyWidth, 5);
	TestCase_assertUIntEqual(copyHeight, 5);
}

static void testCopyGridCells(void) {
	uint8_t sourceBytes[] = {
		1, 2, 3,
		4, 5, 6,
		7, 8, 9
	};
	uint8_t expectedBytes1[] = {
		0, 0, 0,
		0, 0, 0,
		0, 1, 2
	};
	uint8_t expectedBytes2[] = {
		5, 6, 0,
		8, 9, 0,
		0, 1, 2
	};
	uint8_t expectedBytes3[] = {
		1, 2, 0,
		4, 5, 0,
		0, 0, 0
	};
	uint8_t expectedBytes4[] = {
		0, 0, 0,
		2, 3, 0,
		5, 6, 0
	};
	uint8_t expectedBytes5[] = {
		0, 0, 0,
		0, 1, 0,
		0, 0, 0
	};
	uint8_t targetBytes[9];
	
	copyGridCells(targetBytes, sourceBytes, 3, 3, 3, 3, 1, 0, 0, 0, 0, 3, 3);
	assertBytesEqual(targetBytes, sourceBytes, 3, 3, __LINE__);
	
	memset(targetBytes, 0, sizeof(targetBytes));
	copyGridCells(targetBytes, sourceBytes, 3, 3, 3, 3, 1, 0, 0, 1, 2, 3, 3);
	assertBytesEqual(targetBytes, expectedBytes1, 3, 3, __LINE__);
	
	copyGridCells(targetBytes, sourceBytes, 3, 3, 3, 3, 1, 1, 1, 0, 0, 3, 3);
	assertBytesEqual(targetBytes, expectedBytes2, 3, 3, __LINE__);
	
	memset(targetBytes, 0, sizeof(targetBytes));
	copyGridCells(targetBytes, sourceBytes, 3, 3, 3, 3, 1, 0, 0, 0, 0, 2, 2);
	assertBytesEqual(targetBytes, expectedBytes3, 3, 3, __LINE__);
	
	memset(targetBytes, 0, sizeof(targetBytes));
	copyGridCells(targetBytes, sourceBytes, 3, 3, 3, 3, 1, 0, 0, -1, 1, 3, 3);
	assertBytesEqual(targetBytes, expectedBytes4, 3, 3, __LINE__);
	
	memset(targetBytes, 0, sizeof(targetBytes));
	copyGridCells(targetBytes, sourceBytes, 3, 3, 3, 3, 1, -1, -1, 0, 0, 2, 2);
	assertBytesEqual(targetBytes, expectedBytes5, 3, 3, __LINE__);
}

static void testFlipGridHorizontal(void) {
	uint8_t cells1[] = {
		0x00, 0x01, 0x02, 0x03, 0x04,
		0x05, 0x06, 0x07, 0x08, 0x09,
		0x0A, 0x0B, 0x0C, 0x0D, 0x0E,
		0x0F, 0x10, 0x11, 0x12, 0x13
	};
	uint8_t cells2[] = {
		0x00,0x02, 0x04,0x06, 0x08,0x0A, 0x0C,0x0E,
		0x10,0x12, 0x14,0x16, 0x18,0x1A, 0x1C,0x1E,
		0x20,0x22, 0x24,0x26, 0x28,0x2A, 0x2C,0x2E
	};
	uint8_t cells3[] = {
		0x00,0x01,0x02, 0x03,0x04,0x05,
		0x06,0x07,0x08, 0x09,0x0A,0x0B,
		0x0C,0x0D,0x0E, 0x0F,0x10,0x11
	};
	uint8_t cells4[] = {
		0x00,0x01,0x02,0x03, 0x04,0x05,0x06,0x07, 0x08,0x09,0x0A,0x0B,
		0x0C,0x0D,0x0E,0x0F, 0x10,0x11,0x12,0x13, 0x14,0x15,0x16,0x17
	};
	uint8_t cells8[] = {
		0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07, 0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,
		0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17, 0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F
	};
	uint8_t expectedCells1[] = {
		0x04, 0x03, 0x02, 0x01, 0x00,
		0x09, 0x08, 0x07, 0x06, 0x05,
		0x0E, 0x0D, 0x0C, 0x0B, 0x0A,
		0x13, 0x12, 0x11, 0x10, 0x0F
	};
	uint8_t expectedCells2[] = {
		0x0C,0x0E, 0x08,0x0A, 0x04,0x06, 0x00,0x02,
		0x1C,0x1E, 0x18,0x1A, 0x14,0x16, 0x10,0x12,
		0x2C,0x2E, 0x28,0x2A, 0x24,0x26, 0x20,0x22
	};
	uint8_t expectedCells3[] = {
		0x03,0x04,0x05, 0x00,0x01,0x02,
		0x09,0x0A,0x0B, 0x06,0x07,0x08,
		0x0F,0x10,0x11, 0x0C,0x0D,0x0E
	};
	uint8_t expectedCells4[] = {
		0x08,0x09,0x0A,0x0B, 0x04,0x05,0x06,0x07, 0x00,0x01,0x02,0x03,
		0x14,0x15,0x16,0x17, 0x10,0x11,0x12,0x13, 0x0C,0x0D,0x0E,0x0F
	};
	uint8_t expectedCells8[] = {
		0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F, 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
		0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F, 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17
	};
	
	flipGridHorizontal(cells1, 5, 4, 1);
	assertBytesEqual(cells1, expectedCells1, 5, 4, __LINE__);
	
	flipGridHorizontal(cells2, 4, 3, 2);
	assertBytesEqual(cells2, expectedCells2, 4, 3, __LINE__);
	
	flipGridHorizontal(cells3, 2, 3, 3);
	assertBytesEqual(cells3, expectedCells3, 3, 2, __LINE__);
	
	flipGridHorizontal(cells4, 3, 2, 4);
	assertBytesEqual(cells4, expectedCells4, 3, 2, __LINE__);
	
	flipGridHorizontal(cells8, 2, 2, 8);
	assertBytesEqual(cells8, expectedCells8, 2, 2, __LINE__);
}

static void testFlipGridVertical(void) {
	uint8_t cells1[] = {
		0x00, 0x01, 0x02, 0x03, 0x04,
		0x05, 0x06, 0x07, 0x08, 0x09,
		0x0A, 0x0B, 0x0C, 0x0D, 0x0E,
		0x0F, 0x10, 0x11, 0x12, 0x13
	};
	uint8_t cells2[] = {
		0x00,0x02, 0x04,0x06, 0x08,0x0A, 0x0C,0x0E,
		0x10,0x12, 0x14,0x16, 0x18,0x1A, 0x1C,0x1E,
		0x20,0x22, 0x24,0x26, 0x28,0x2A, 0x2C,0x2E
	};
	uint8_t cells3[] = {
		0x00,0x01,0x02, 0x03,0x04,0x05,
		0x06,0x07,0x08, 0x09,0x0A,0x0B,
		0x0C,0x0D,0x0E, 0x0F,0x10,0x11
	};
	uint8_t cells4[] = {
		0x00,0x01,0x02,0x03, 0x04,0x05,0x06,0x07, 0x08,0x09,0x0A,0x0B,
		0x0C,0x0D,0x0E,0x0F, 0x10,0x11,0x12,0x13, 0x14,0x15,0x16,0x17
	};
	uint8_t cells8[] = {
		0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07, 0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,
		0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17, 0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F
	};
	uint8_t expectedCells1[] = {
		0x0F, 0x10, 0x11, 0x12, 0x13,
		0x0A, 0x0B, 0x0C, 0x0D, 0x0E,
		0x05, 0x06, 0x07, 0x08, 0x09,
		0x00, 0x01, 0x02, 0x03, 0x04
	};
	uint8_t expectedCells2[] = {
		0x20,0x22, 0x24,0x26, 0x28,0x2A, 0x2C,0x2E,
		0x10,0x12, 0x14,0x16, 0x18,0x1A, 0x1C,0x1E,
		0x00,0x02, 0x04,0x06, 0x08,0x0A, 0x0C,0x0E
	};
	uint8_t expectedCells3[] = {
		0x0C,0x0D,0x0E, 0x0F,0x10,0x11,
		0x06,0x07,0x08, 0x09,0x0A,0x0B,
		0x00,0x01,0x02, 0x03,0x04,0x05
	};
	uint8_t expectedCells4[] = {
		0x0C,0x0D,0x0E,0x0F, 0x10,0x11,0x12,0x13, 0x14,0x15,0x16,0x17,
		0x00,0x01,0x02,0x03, 0x04,0x05,0x06,0x07, 0x08,0x09,0x0A,0x0B
	};
	uint8_t expectedCells8[] = {
		0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17, 0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,
		0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07, 0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F
	};
	
	flipGridVertical(cells1, 5, 4, 1);
	assertBytesEqual(cells1, expectedCells1, 5, 4, __LINE__);
	
	flipGridVertical(cells2, 4, 3, 2);
	assertBytesEqual(cells2, expectedCells2, 4, 3, __LINE__);
	
	flipGridVertical(cells3, 2, 3, 3);
	assertBytesEqual(cells3, expectedCells3, 3, 2, __LINE__);
	
	flipGridVertical(cells4, 3, 2, 4);
	assertBytesEqual(cells4, expectedCells4, 3, 2, __LINE__);
	
	flipGridVertical(cells8, 2, 2, 8);
	assertBytesEqual(cells8, expectedCells8, 2, 2, __LINE__);
}

static void testRotateGrid180(void) {
	uint8_t cells1[] = {
		0x00, 0x01, 0x02, 0x03, 0x04,
		0x05, 0x06, 0x07, 0x08, 0x09,
		0x0A, 0x0B, 0x0C, 0x0D, 0x0E,
		0x0F, 0x10, 0x11, 0x12, 0x13
	};
	uint8_t cells2[] = {
		0x00,0x02, 0x04,0x06, 0x08,0x0A, 0x0C,0x0E,
		0x10,0x12, 0x14,0x16, 0x18,0x1A, 0x1C,0x1E,
		0x20,0x22, 0x24,0x26, 0x28,0x2A, 0x2C,0x2E
	};
	uint8_t cells3[] = {
		0x00,0x01,0x02, 0x03,0x04,0x05,
		0x06,0x07,0x08, 0x09,0x0A,0x0B,
		0x0C,0x0D,0x0E, 0x0F,0x10,0x11
	};
	uint8_t cells4[] = {
		0x00,0x01,0x02,0x03, 0x04,0x05,0x06,0x07, 0x08,0x09,0x0A,0x0B,
		0x0C,0x0D,0x0E,0x0F, 0x10,0x11,0x12,0x13, 0x14,0x15,0x16,0x17
	};
	uint8_t cells8[] = {
		0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07, 0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,
		0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17, 0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F
	};
	uint8_t expectedCells1[] = {
		0x13, 0x12, 0x11, 0x10, 0x0F,
		0x0E, 0x0D, 0x0C, 0x0B, 0x0A,
		0x09, 0x08, 0x07, 0x06, 0x05,
		0x04, 0x03, 0x02, 0x01, 0x00
	};
	uint8_t expectedCells2[] = {
		0x2C,0x2E, 0x28,0x2A, 0x24,0x26, 0x20,0x22,
		0x1C,0x1E, 0x18,0x1A, 0x14,0x16, 0x10,0x12,
		0x0C,0x0E, 0x08,0x0A, 0x04,0x06, 0x00,0x02
	};
	uint8_t expectedCells3[] = {
		0x0F,0x10,0x11, 0x0C,0x0D,0x0E,
		0x09,0x0A,0x0B, 0x06,0x07,0x08,
		0x03,0x04,0x05, 0x00,0x01,0x02
	};
	uint8_t expectedCells4[] = {
		0x14,0x15,0x16,0x17, 0x10,0x11,0x12,0x13, 0x0C,0x0D,0x0E,0x0F,
		0x08,0x09,0x0A,0x0B, 0x04,0x05,0x06,0x07, 0x00,0x01,0x02,0x03
	};
	uint8_t expectedCells8[] = {
		0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F, 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,
		0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F, 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07
	};
	
	rotateGrid180(cells1, 5, 4, 1);
	assertBytesEqual(cells1, expectedCells1, 5, 4, __LINE__);
	
	rotateGrid180(cells2, 4, 3, 2);
	assertBytesEqual(cells2, expectedCells2, 4, 3, __LINE__);
	
	rotateGrid180(cells3, 2, 3, 3);
	assertBytesEqual(cells3, expectedCells3, 3, 2, __LINE__);
	
	rotateGrid180(cells4, 3, 2, 4);
	assertBytesEqual(cells4, expectedCells4, 3, 2, __LINE__);
	
	rotateGrid180(cells8, 2, 2, 8);
	assertBytesEqual(cells8, expectedCells8, 2, 2, __LINE__);
}

static void testRotateGrid90CW(void) {
	uint8_t cells1[] = {
		0x00, 0x01, 0x02, 0x03, 0x04,
		0x05, 0x06, 0x07, 0x08, 0x09,
		0x0A, 0x0B, 0x0C, 0x0D, 0x0E,
		0x0F, 0x10, 0x11, 0x12, 0x13
	};
	uint8_t cells2[] = {
		0x00,0x02, 0x04,0x06, 0x08,0x0A, 0x0C,0x0E,
		0x10,0x12, 0x14,0x16, 0x18,0x1A, 0x1C,0x1E,
		0x20,0x22, 0x24,0x26, 0x28,0x2A, 0x2C,0x2E
	};
	uint8_t cells3[] = {
		0x00,0x01,0x02, 0x03,0x04,0x05,
		0x06,0x07,0x08, 0x09,0x0A,0x0B,
		0x0C,0x0D,0x0E, 0x0F,0x10,0x11
	};
	uint8_t cells4[] = {
		0x00,0x01,0x02,0x03, 0x04,0x05,0x06,0x07, 0x08,0x09,0x0A,0x0B,
		0x0C,0x0D,0x0E,0x0F, 0x10,0x11,0x12,0x13, 0x14,0x15,0x16,0x17
	};
	uint8_t cells8[] = {
		0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07, 0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,
		0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17, 0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F
	};
	uint8_t expectedCells1[] = {
		0x0F, 0x0A, 0x05, 0x00,
		0x10, 0x0B, 0x06, 0x01,
		0x11, 0x0C, 0x07, 0x02,
		0x12, 0x0D, 0x08, 0x03,
		0x13, 0x0E, 0x09, 0x04
	};
	uint8_t expectedCells2[] = {
		0x20,0x22, 0x10,0x12, 0x00,0x02,
		0x24,0x26, 0x14,0x16, 0x04,0x06,
		0x28,0x2A, 0x18,0x1A, 0x08,0x0A,
		0x2C,0x2E, 0x1C,0x1E, 0x0C,0x0E
	};
	uint8_t expectedCells3[] = {
		0x0C,0x0D,0x0E, 0x06,0x07,0x08, 0x00,0x01,0x02,
		0x0F,0x10,0x11, 0x09,0x0A,0x0B, 0x03,0x04,0x05
	};
	uint8_t expectedCells4[] = {
		0x0C,0x0D,0x0E,0x0F, 0x00,0x01,0x02,0x03,
		0x10,0x11,0x12,0x13, 0x04,0x05,0x06,0x07,
		0x14,0x15,0x16,0x17, 0x08,0x09,0x0A,0x0B
	};
	uint8_t expectedCells8[] = {
		0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17, 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
		0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F, 0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F
	};
	
	rotateGrid90CW(cells1, 5, 4, 1);
	assertBytesEqual(cells1, expectedCells1, 4, 5, __LINE__);
	
	rotateGrid90CW(cells2, 4, 3, 2);
	assertBytesEqual(cells2, expectedCells2, 3, 4, __LINE__);
	
	rotateGrid90CW(cells3, 2, 3, 3);
	assertBytesEqual(cells3, expectedCells3, 2, 3, __LINE__);
	
	rotateGrid90CW(cells4, 3, 2, 4);
	assertBytesEqual(cells4, expectedCells4, 2, 3, __LINE__);
	
	rotateGrid90CW(cells8, 2, 2, 8);
	assertBytesEqual(cells8, expectedCells8, 2, 2, __LINE__);
}

static void testRotateGrid90CCW(void) {
	uint8_t cells1[] = {
		0x00, 0x01, 0x02, 0x03, 0x04,
		0x05, 0x06, 0x07, 0x08, 0x09,
		0x0A, 0x0B, 0x0C, 0x0D, 0x0E,
		0x0F, 0x10, 0x11, 0x12, 0x13
	};
	uint8_t cells2[] = {
		0x00,0x02, 0x04,0x06, 0x08,0x0A, 0x0C,0x0E,
		0x10,0x12, 0x14,0x16, 0x18,0x1A, 0x1C,0x1E,
		0x20,0x22, 0x24,0x26, 0x28,0x2A, 0x2C,0x2E
	};
	uint8_t cells3[] = {
		0x00,0x01,0x02, 0x03,0x04,0x05,
		0x06,0x07,0x08, 0x09,0x0A,0x0B,
		0x0C,0x0D,0x0E, 0x0F,0x10,0x11
	};
	uint8_t cells4[] = {
		0x00,0x01,0x02,0x03, 0x04,0x05,0x06,0x07, 0x08,0x09,0x0A,0x0B,
		0x0C,0x0D,0x0E,0x0F, 0x10,0x11,0x12,0x13, 0x14,0x15,0x16,0x17
	};
	uint8_t cells8[] = {
		0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07, 0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,
		0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17, 0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F
	};
	uint8_t expectedCells1[] = {
		0x04, 0x09, 0x0E, 0x13,
		0x03, 0x08, 0x0D, 0x12,
		0x02, 0x07, 0x0C, 0x11,
		0x01, 0x06, 0x0B, 0x10,
		0x00, 0x05, 0x0A, 0x0F
	};
	uint8_t expectedCells2[] = {
		0x0C,0x0E, 0x1C,0x1E, 0x2C,0x2E,
		0x08,0x0A, 0x18,0x1A, 0x28,0x2A,
		0x04,0x06, 0x14,0x16, 0x24,0x26,
		0x00,0x02, 0x10,0x12, 0x20,0x22
	};
	uint8_t expectedCells3[] = {
		0x03,0x04,0x05, 0x09,0x0A,0x0B, 0x0F,0x10,0x11,
		0x00,0x01,0x02, 0x06,0x07,0x08, 0x0C,0x0D,0x0E
	};
	uint8_t expectedCells4[] = {
		0x08,0x09,0x0A,0x0B, 0x14,0x15,0x16,0x17,
		0x04,0x05,0x06,0x07, 0x10,0x11,0x12,0x13,
		0x00,0x01,0x02,0x03, 0x0C,0x0D,0x0E,0x0F
	};
	uint8_t expectedCells8[] = {
		0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F, 0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,
		0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07, 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17
	};
	
	rotateGrid90CCW(cells1, 5, 4, 1);
	assertBytesEqual(cells1, expectedCells1, 4, 5, __LINE__);
	
	rotateGrid90CCW(cells2, 4, 3, 2);
	assertBytesEqual(cells2, expectedCells2, 3, 4, __LINE__);
	
	rotateGrid90CCW(cells3, 2, 3, 3);
	assertBytesEqual(cells3, expectedCells3, 2, 3, __LINE__);
	
	rotateGrid90CCW(cells4, 3, 2, 4);
	assertBytesEqual(cells4, expectedCells4, 2, 3, __LINE__);
	
	rotateGrid90CCW(cells8, 2, 2, 8);
	assertBytesEqual(cells8, expectedCells8, 2, 2, __LINE__);
}

TEST_SUITE(GridTest,
           testClampGridCopyRegion,
           testCopyGridCells,
           testFlipGridHorizontal,
           testFlipGridVertical,
           testRotateGrid90CW,
           testRotateGrid90CCW,
           testRotateGrid180)
