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

static void testCreate(void) {
	StringDiff stringDiff = StringDiff_create(NULL, NULL);
	TestCase_assertPointerNULL(stringDiff.bytes);
	TestCase_assertSizeEqual(stringDiff.length, 0);
	TestCase_assertIntEqual(stringDiff.lengthChange, 0);
	TestCase_assertUIntEqual(stringDiff.isNull, 0x3);
	StringDiff_dispose(&stringDiff);
	
	stringDiff = StringDiff_create(NULL, "");
	TestCase_assertPointerNULL(stringDiff.bytes);
	TestCase_assertSizeEqual(stringDiff.length, 0);
	TestCase_assertIntEqual(stringDiff.lengthChange, 0);
	TestCase_assertUIntEqual(stringDiff.isNull, 0x1);
	StringDiff_dispose(&stringDiff);
	
	stringDiff = StringDiff_create("", NULL);
	TestCase_assertPointerNULL(stringDiff.bytes);
	TestCase_assertSizeEqual(stringDiff.length, 0);
	TestCase_assertIntEqual(stringDiff.lengthChange, 0);
	TestCase_assertUIntEqual(stringDiff.isNull, 0x2);
	StringDiff_dispose(&stringDiff);
	
	stringDiff = StringDiff_create("", "");
	TestCase_assertPointerNULL(stringDiff.bytes);
	TestCase_assertSizeEqual(stringDiff.length, 0);
	TestCase_assertIntEqual(stringDiff.lengthChange, 0);
	TestCase_assertUIntEqual(stringDiff.isNull, 0x0);
	StringDiff_dispose(&stringDiff);
	
	stringDiff = StringDiff_create(NULL, "a");
	TestCase_assertPointerNonNULL(stringDiff.bytes);
	TestCase_assertBytesEqual(stringDiff.bytes, "a", 1);
	TestCase_assertSizeEqual(stringDiff.length, 1);
	TestCase_assertIntEqual(stringDiff.lengthChange, 1);
	TestCase_assertUIntEqual(stringDiff.isNull, 0x1);
	StringDiff_dispose(&stringDiff);
	
	stringDiff = StringDiff_create("a", NULL);
	TestCase_assertPointerNonNULL(stringDiff.bytes);
	TestCase_assertBytesEqual(stringDiff.bytes, "a", 1);
	TestCase_assertSizeEqual(stringDiff.length, 1);
	TestCase_assertIntEqual(stringDiff.lengthChange, -1);
	TestCase_assertUIntEqual(stringDiff.isNull, 0x2);
	StringDiff_dispose(&stringDiff);
	
	stringDiff = StringDiff_create("", "a");
	TestCase_assertPointerNonNULL(stringDiff.bytes);
	TestCase_assertBytesEqual(stringDiff.bytes, "a", 1);
	TestCase_assertSizeEqual(stringDiff.length, 1);
	TestCase_assertIntEqual(stringDiff.lengthChange, 1);
	TestCase_assertUIntEqual(stringDiff.isNull, 0x0);
	StringDiff_dispose(&stringDiff);
	
	stringDiff = StringDiff_create("a", "");
	TestCase_assertPointerNonNULL(stringDiff.bytes);
	TestCase_assertBytesEqual(stringDiff.bytes, "a", 1);
	TestCase_assertSizeEqual(stringDiff.length, 1);
	TestCase_assertIntEqual(stringDiff.lengthChange, -1);
	TestCase_assertUIntEqual(stringDiff.isNull, 0x0);
	StringDiff_dispose(&stringDiff);
	
	stringDiff = StringDiff_create("abcd", "ab");
	TestCase_assertPointerNonNULL(stringDiff.bytes);
	TestCase_assertBytesEqual(stringDiff.bytes, "\x00\x00""cd", 4);
	TestCase_assertSizeEqual(stringDiff.length, 4);
	TestCase_assertIntEqual(stringDiff.lengthChange, -2);
	TestCase_assertUIntEqual(stringDiff.isNull, 0x0);
	StringDiff_dispose(&stringDiff);
	
	stringDiff = StringDiff_create("ab", "abcd");
	TestCase_assertPointerNonNULL(stringDiff.bytes);
	TestCase_assertBytesEqual(stringDiff.bytes, "\x00\x00""cd", 4);
	TestCase_assertSizeEqual(stringDiff.length, 4);
	TestCase_assertIntEqual(stringDiff.lengthChange, 2);
	TestCase_assertUIntEqual(stringDiff.isNull, 0x0);
	StringDiff_dispose(&stringDiff);
	
	stringDiff = StringDiff_create("aBc", "abc");
	TestCase_assertPointerNonNULL(stringDiff.bytes);
	TestCase_assertBytesEqual(stringDiff.bytes, "\x00\x20\x00", 3);
	TestCase_assertSizeEqual(stringDiff.length, 3);
	TestCase_assertIntEqual(stringDiff.lengthChange, 0);
	TestCase_assertUIntEqual(stringDiff.isNull, 0x0);
	StringDiff_dispose(&stringDiff);
	
	stringDiff = StringDiff_create("ab", "Abc");
	TestCase_assertPointerNonNULL(stringDiff.bytes);
	TestCase_assertBytesEqual(stringDiff.bytes, "\x20\x00""c", 3);
	TestCase_assertSizeEqual(stringDiff.length, 3);
	TestCase_assertIntEqual(stringDiff.lengthChange, 1);
	TestCase_assertUIntEqual(stringDiff.isNull, 0x0);
	StringDiff_dispose(&stringDiff);
}

static void testApplyRevert(void) {
	StringDiff stringDiff = StringDiff_create("ab", "Abc");
	char * string = strdup("ab");
	StringDiff_apply(&stringDiff, &string);
	TestCase_assertStringEqual(string, "Abc");
	StringDiff_revert(&stringDiff, &string);
	TestCase_assertStringEqual(string, "ab");
	free(string);
	StringDiff_dispose(&stringDiff);
	
	stringDiff = StringDiff_create("ab", "aa");
	string = strdup("aa");
	StringDiff_revert(&stringDiff, &string);
	TestCase_assertStringEqual(string, "ab");
	StringDiff_apply(&stringDiff, &string);
	TestCase_assertStringEqual(string, "aa");
	free(string);
	StringDiff_dispose(&stringDiff);
	
	stringDiff = StringDiff_create("a", NULL);
	string = NULL;
	StringDiff_revert(&stringDiff, &string);
	TestCase_assertStringEqual(string, "a");
	StringDiff_apply(&stringDiff, &string);
	TestCase_assertPointerNULL(string);
	StringDiff_dispose(&stringDiff);
	
	stringDiff = StringDiff_create(NULL, "b");
	string = strdup("b");
	StringDiff_revert(&stringDiff, &string);
	TestCase_assertPointerNULL(string);
	StringDiff_apply(&stringDiff, &string);
	TestCase_assertStringEqual(string, "b");
	free(string);
	StringDiff_dispose(&stringDiff);
	
	stringDiff = StringDiff_create(NULL, NULL);
	string = NULL;
	StringDiff_apply(&stringDiff, &string);
	TestCase_assertPointerNULL(string);
	StringDiff_revert(&stringDiff, &string);
	TestCase_assertPointerNULL(string);
	StringDiff_dispose(&stringDiff);
	
	stringDiff = StringDiff_create("", NULL);
	string = NULL;
	StringDiff_revert(&stringDiff, &string);
	TestCase_assertPointerNonNULL(string);
	TestCase_assertStringEqual(string, "");
	StringDiff_apply(&stringDiff, &string);
	TestCase_assertPointerNULL(string);
	StringDiff_dispose(&stringDiff);
	
	stringDiff = StringDiff_create(NULL, "");
	string = NULL;
	StringDiff_apply(&stringDiff, &string);
	TestCase_assertPointerNonNULL(string);
	TestCase_assertStringEqual(string, "");
	StringDiff_revert(&stringDiff, &string);
	TestCase_assertPointerNULL(string);
	StringDiff_dispose(&stringDiff);
	
	stringDiff = StringDiff_create("Something longer to force a larger reallocation", "aa");
	string = strdup("aa");
	StringDiff_revert(&stringDiff, &string);
	TestCase_assertStringEqual(string, "Something longer to force a larger reallocation");
	StringDiff_apply(&stringDiff, &string);
	TestCase_assertStringEqual(string, "aa");
	free(string);
	StringDiff_dispose(&stringDiff);
	
	stringDiff = StringDiff_create("Mid-string addition", "Mid-string word addition");
	string = strdup("Mid-string word addition");
	StringDiff_revert(&stringDiff, &string);
	TestCase_assertStringEqual(string, "Mid-string addition");
	StringDiff_apply(&stringDiff, &string);
	TestCase_assertStringEqual(string, "Mid-string word addition");
	free(string);
	StringDiff_dispose(&stringDiff);
	
	stringDiff = StringDiff_create("Mid-string word deletion", "Mid-string deletion");
	string = strdup("Mid-string deletion");
	StringDiff_revert(&stringDiff, &string);
	TestCase_assertStringEqual(string, "Mid-string word deletion");
	StringDiff_apply(&stringDiff, &string);
	TestCase_assertStringEqual(string, "Mid-string deletion");
	free(string);
	StringDiff_dispose(&stringDiff);
}

TEST_SUITE(StringDiffTest,
           testCreate,
           testApplyRevert)
